함수의 return문 위에서 바로 하고 싶은 동작(Side Effect)를 실행시킨다
1. 문제점
React에서 Side Effect를 발생시키기 위한 조건
- 렌더링을 Blocking 하지 않기 위해서 렌더링이 모두 완료되고 난 후에 실행할 수 있어야 함
- 매 렌더링마다 실행되는 것이 아니라 원할때만 조건부로 실행할 수 있어야 함
useEffect(콜백함수)
: 하나의 함수를 인자로 받고 useEffect의 동작은 렌더링이 완료된 후 (JSX return 후)에, 콜백함수를 실행한다
1. Side Effect가 렌더링을 blocking하는 문제 해결
import { useEffect } from 'react';
const App = () => {
console.log("side effect")
useEffect(() => {
console.log("side effect with useEffect")
});
console.log("render");
return <h1>Hello, Wecoder</h1>;
};
콘솔창에는 side effect
> render
> side effect with useEffect
순으로 출력된다.
import { useEffect, useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
//useEffect(() => {
// console.log("side effect with useEffect")
//})
useEffect(() => {
console.log("count changed")
}, [count]); //count의 값이 변했을 때만 이 콜백함수를 호출
console.log("render");
return (
<div>
<div className="wrapper">
<button
onClick={() => setCount(count+1)}>Up
</button>
</div>
<input
value={text}
onChange={(e) => setText(e.target.value)}
/>
</div>
);
};
처음 콘솔창에 useEffect()를 사용했기 때문에 render
> side effect with useEffect
가 출력된다
그러나 버튼을 클릭하거나 input에 값을 입력할 때 마다 콘솔창에 render
> side effect with useEffect
가 출력된다. useState() 함수에서 값이 매번 바뀔때 마다 리렌더링 되기 때문
useEffect(콜백함수, 의존성 배열)
을 사용하면 리렌더링 문제가 해결된다
- 의존성 배열을 전달 하면 useEffect 함수는 먼저 의존성 배열의 값을 검사한다
- 의존성 배열에 들어가 있는 값이 이전 렌더링과 비교했을 때 동일한지를 검사
- 첫번째 렌더링에서는 무조건 콜백함수를 호출
- 두번째 렌더링부터는 의존성 배열의 값이 변했을때만 콜백함수를 호출한다
처음 콘솔창에render
>count changed
출력
버튼을 클릭하면 콘솔창에render
>count changed
한번 더 출력
input값을 입력하면render
만 출력됨
처음 렌더링에서 한번만 실행되게 하는 방법 :
useEffect(() => {콜백함수}, [])
의존성 배열을[]
빈 배열로 입력해 두면 콜백함수가 첫 렌더링에서만 한 번 실행된다
effect를 정리하고 치우는 작업
남아 있는 이펙트를 한 번 정리를 해주고 치운 다음 새로운 이펙트를 발생 시키거나 또는 최종적으로 치워줄 필요가 있다
clean up 이 필요없는 effect : 코드의 동작에 아무런 영향을 미치지 않는 effect
clean up 이 필요한 effect : 지속적으로 구독을 하면서 남아있는 effect
clean up을 하면서 동작하고 싶은 것을 함수 형태로 만들어서 return한다
다음 이펙트가 발생하기 전에 기존에 부착해둔 eventListener 를 제거
useEffect(() => {
const button = document.getElementById('consoleButton');
const printConsole = () => {
console.log('button clicked');
};
button.addEventListener('click', printConsole);
// side effect를 clean up 하기 위한 함수를 선언한다.
const cleanUp = () => {
button.removeEventListener('click', printConsole);
};
// clean up 함수를 return 한다.
return cleanUp;
});
return () => {
button.removeEventListener('click', printConsole);
};