어떠한 컴포넌트가 Mount(화면에 첫 렌더링) / Update(특정 props가 바뀔때) / Unmount (화면에서 사라질 때) 되었을 때 특정 작업을 처리할 코드를 실행시켜주기 위해 useEffect
를 사용한다.
📌 useEffect( ( ) => { } )
useEffect hook
은 인자로 콜백함수를 받는다.
콜백 함수란 다른 함수의 인자로 전달된 함수를 의미한다.
이 콜백 함수 내부에 우리가 원하는 작업을 해줄 코드를 작성하여준다.
useEffect
의 인자로 하나의 콜백함수만 받는 형태useEffect
의 첫 번째 인자로 콜백 함수, 두번째 인자로 배열을 받는 형태defendency array
라고 한다.ex) 타이머라고 치면 더이상 타이머가 필요 없을 때 타이머를 멈추는 정리 작업
ex) 어떤 이벤트리스너를 등록을 했다면 컴포넌트가 언마운트 될 때 등록한 이벤트를 제거해주는 작업
이러한 정리 작업을 처리하려면 useEffect
의 return 값으로 함수를 넣어준다.
그러면 해당 컴포넌트가 언마운트될 때 혹은 다음 렌더링 시 불릴 useEffect
가 실행되기 이전에 그 함수가 실행이 된다.
import React, { useState, useEffect } from "react";
const SideEffect = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
// count 값이 변했을 때만 이 콜백함수를 호출되고 text값이 변할 때는 useEffecdt의 콜백함수가 호출되지 않는다.
useEffect(() => {
console.log("count changed");
}, [count]);
// 반대로, text 값이 변했을 때만 이 콜백함수를 호출되지만 count값이 변할 때는 이 useEffect는 실행되지 않는다.
useEffect(() => {
console.log("text changed");
}, [text]);
// count와 text 둘 중 하나라도 변했다면, 이 useEffect는 실행된다.
useEffect(() => {
console.log("count & text when?");
}, [count, text]); //
// 첫 번째 렌더링에서만 실행되고 두번째부터 마지막까지 절대 호출되지 않기를 원한다면, 의존생 배열에 [] 빈 배열을 넣는다.
// 감지할 값이 없기때문에 첫번째 렌더링시에만 effect가 호출된다.
useEffect(() => {
console.log("only first render");
}, []);
useEffect(() => {
console.log("------------------");
});
console.log("count", count);
console.log("text", text);
console.log("Render");
return (
<div>
<div className="wrapper">
<h1>Count : {count}</h1>
<button onClick={() => setCount(count + 1)}>count up</button>
</div>
<input
onChange={(e) => setText(e.target.value)}
type="text"
value={text}
/>
</div>
);
};
export default SideEffect;
import React, { useState, useEffect } from "react";
// 1. 컴포넌트를 count라는 state를 가지고 있고 useState를 통해
// 버튼을 눌렀을 떄 state인 count가 올라가게끔 만들어준다.
// 2. useEffect 를 사용한다.
function UseEffect() {
const [count, setCount] = useState(1);
const [name, setName] = useState("");
const handleCountUpdate = () => {
setCount(count + 1);
};
const handleInputChange = (e) => {
setName(e.target.value);
};
// 콘솔창이 언제 출력되는지 아래 코드를 실행시켜보자.
// 렌더링마다 매번 실햄됨.
useEffect(() => {
console.log("렌더링 지옥!");
});
// 마운팅 + name이 변경될때만 실행.
useEffect(() => {
console.log("name 변화");
}, [name]);
// 마운팅 + count가 변화될때마다 실행.
useEffect(() => {
console.log("count 변화");
}, [count]);
// useEffect를 맨 처음 화면 렌더링될때만 부르고 싶다면?
// dependecy array를 빈 배열로 두번째 인자에 넣어두면된다.
useEffect(() => {
console.log("mounting!");
}, []);
return (
<div>
<div>
<button onClick={handleCountUpdate}>Update</button>
<span>count : {count}</span>
</div>
<div>
<input type="text" value={name} onChange={handleInputChange} />
<span>name: {name} </span>
</div>
</div>
);
}
export default UseEffect;
component 폴더를 하나 생성하고 그 안에 Timer.js파일을 만든다.
//Timer.js
import React, { useEffect } from "react";
const Timer = (props) => {
useEffect(() => {
// setInterval : 정해진 주기마다 특정 로직을 반복해야할 때 사용하는 메서드.
// 정리 작업을 해주는 코드가 없을 경우,
// 타이머가 언마운트 되었을 때 1초마다 찍히는 콘솔창이 멈추지 않고 계속 작동될 것이다.
// 정리 작업을 해주는 코드를 추가하여 타이머가 언마운트 되었을 때 timer가 종료되도록(멈추도록)해보자!
// 정리를 하려면? useEffect의 return 값으로 함수를 넣어준다. 그리고 그 함수 안에서 정리작업을 처리해준다.
const timer = setInterval(() => {
console.log("타이머 돌아가는중...");
}, 1000);
return () => {
clearInterval(timer);
console.log("타이머가 종료되었습니다!");
};
}, []);
return (
<div>
<span>타이머를 시작합니다. 콘솔을 보세요.</span>
</div>
);
};
export default Timer;
💡 App.js에 component 인 Timer import해야 화면에 렌더링되니 잊지말기!
//App.js//
import React, { useState, useEffect } from "react";
import Timer from "./component/Timer";
// Timer component를 계속 보여주는게 아니라 showTimer가 true일때만 타이머를 보여주고싶다.
function App() {
const [showTimer, setShowTimer] = useState(false);
return (
<div>
{/* 아래 코드가 쇼타이머가 true일때만 Timer를 보여주겠다는 코드 */}
{showTimer && <Timer />}
{/* 버튼이 클릭될 때 쇼타이머가 false->true 혹은 true -> false 로 바뀌게하는 코드 */}
<button onClick={() => setShowTimer(!showTimer)}>Toggle Timer</button>
</div>
);
}
export default App;