useEffect를 배우기 전 state
, props
, event
세 가지 개념을 활용해 워하는 UI화면 을 렌더링 하는 방법을 배웠다.
하지만 웹 사이트를 구현하기 위해 이 세 가지 개념으로는 조금 부족하다.
화면에 보일 수 있는 데이터를 서버에서 받아오기,
state
가 바뀔 때마다 함수를 실행 시키거나
이벤트 리스너를 달았다가 해제하는 등의 동작이 필요할 수 있다.
예시
import React, {useState} from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
console.log("rendering");
return (
<div>
<h1>Count: {count}</h1>
<button onClick={()=>setCount(count + 1)}></button>
</div>
);
}
export default Counter;
버튼을 클릭하면 <h1>
태그 안에 있는 Count: 0이 1씩 증가한다.
이 때 콘솔을 확인하면 "rendering"이라는 문자열이 2번 찍혀있는 것을 볼 수 있다.
onClick
이 발생하여 다시 Counter component를 re-rendering하면서 두 번 출력됨위의 코드에서 console.log는 저번 블로그에 작성했던 Side Effect를 초래한다.
함수 안에 Side Effect를 발생시키는 코드를 작성하면 2가지 문제점이 있다.
doSomeSideEffect()
가 실행되고 console.log("rendering")
이 실행된다.import React, { useState } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
doSomeSideEffect();
console.log("rendering");
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>increase</button>
</div>
);
};
function doSomeSideEffect() {
console.log("side effect strat");
console.log("side effect end");
}
export default Counter;
만약 JSX가 작성된 return 문 전에 `doSomeSideEffect 함수에 5초 이상 걸리는 Side Effect가 있다면?
위에서부터 읽히기 때문에 해당 함수가 끝나기 전까지는 rendering이 되지 않아 return문에 작성된 JSX를 그려내지 못한다. 따라서 5초 이상 UI상에 아무런 그림이 그려지지 않는다.
이후에 버튼을 다시 눌렀을 때, 또 다시 5초 이상을 기다려야 한다. rendering을 다시하기 때문이다.
만약 웹 사이트가 처음에 로드되는데 5초 이상 걸린다. 사용자가 그래도 기다렸다. 그 다음 버튼 하나를 눌렀는데 또 5초 이상 기다린다. 그 사이트 도대체 누가 사용할까?
💥따라서 Side Effect는 rendering을 막으면 안된다!
🔑그럼 어떻게 해야할까???
그럼 side effect가 10초가 걸리든 일단 화면은 나타나고 다음의 일이니깐 그 시간 후에 업데이트만 되면 되니깐 이게 어떨까?
와... 직접 구현하기 빡시네...
React Team: 님들 내가 직접 만들어드림 밑에 코드로 import 하심 됨
import {useEffect} from 'react';
useEffect(()=>{},[])
useEffect
는 함수이다.import React, { useState, useEffect } from "react";
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(doSomeSideEffect);
console.log("rendering");
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>increase</button>
</div>
);
};
function doSomeSideEffect() {
console.log("side effect strat");
console.log("side effect end");
}
export default Counter;
useEffect
의 callback함수로 doSomeSideEffect()
를 부여했더니useEffect
를 먼저 호출했는데 왜? console.log("rendering")
을 먼저 실행?useEffect
를 사용하면 랜더링을 먼저 실행하고 난 다음에 useEffect
의 callback함수를 실행한다.여러개의
useEffect
가 있다면?
사용 횟수에 제한은 없다.
useEffect
가 여러 개 있다면 그들끼리는 순서가 있다.
차곡차곡 외부 저장소에 기억해두고 랜더링이 끝나고 하나하나 실행한다.
따라서 순서가 보장된다.
(아직 side effect
의 문제점을 작성 중이다.)
dependency array 의존성 배열(
useEffect
의 두 번째 매개변수)
Side Effect의 실행 여부를 결정짓는다. 실행 타이밍, Side Effec 실행 해? 말어?를 배열 안의 요소에 따라 결정하는 것
useEffect(doSomeSideEffect); //배열이 없다면 매 랜더링마다 실행하라
useEffect(doSomeSideEffect, [count]);//count가 변했을 때만 side effect를 실행하라
useEffect(doSomeSideEffect, [count, inputValue]); //둘 중 하나라도 변했을 때 side effect를 실행하라
useEffect(doSomeSideEffect,[]);
//초기 랜더링 처음에만 실행한다. 이거 바뀌면 실행해 인데 이거가 없음 그럼 처음에 랜더링 할 때만 실행한다.
// 첫 랜더링 때만 필요한 데이터 가져올 때 사용