2023.02.10
useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook입니다. 쉽게 말해 어떤 컴포넌트가 화면에 보여졌을 때 내가 무언가를 실행하고 싶다면? 또는 어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면? useEffect를 사용한다.
useState와 마찬가지로 React에서 제공하는 훅 (기능) 이므로, import React, { useEffect } from "react"; 로 import 해서 사용한다.
App 컴포넌트가 화면에 렌더링될 때 useEffect 안에 있는 console.log가 실행된다. 컴포넌트가 렌더링 될 때 실행된다. 이게 바로 useEffect 핵심 기능이다.
// src/App.js
import React, { useEffect } from "react";
const App = () => {
useEffect(() => {
// 이 부분이 실행된다.
console.log("hello useEffect");
});
return <div>Home</div>;
}
export default App;
useEffect는 useEffect가 속한 컴포넌트가 화면에 렌더링 될 때 실행된다. 이런 useEffect의 특징에 의해 우리가 의도치않은 동작을 경험할수도 있다.
다음 코드를 보면, input이 있고 value 라는 state를 생성하여 input과 연결시켰다. 이렇게 구현하고 브라우저에 input에 어떤 값을 입력하면 useEffect가 계속 실행되는 것을 볼 수 있다.
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
});
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
}
export default App;
전체 흐름은 아래와 같다.
그래서 콘솔이 브라우저에 한번만 찍히길 원했지만, input을 입력할 때마다 계속 찍히고 있는 것이다. 하지만 이런 부분도 해결할 수 있다.
useEffect에는 의존성 배열이라는 것이 있다. 쉽게 풀어 얘기하면 “이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게” 라는 것이다.
// useEffect의 두번째 인자가 의존성 배열이 들어가는 곳 입니다.
useEffect(()=>{
// 실행하고 싶은 함수
}, [의존성배열])
의존성 배열안에는 어떠한 값도 넣지 않았다. 의존성 배열이 “이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게” 라는 의미를 가진다고 했고 아무것도 넣지 않았으니 useEffect는 처음에 딱 한번만 실행되고 그 이후로는 어떤일이 일어나도 실행이 되서는 안된다.
// src/App.js
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
}, []); // 비어있는 의존성 배열
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
}
export default App;
그럼 이제 의존성 배열에 value 를 넣어본다면, value는 state이고 우리가 input을 입력할 때마다 그 값이 변하게 되니 useEffect도 계속 실행이 될것이다.
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
}, [value]); // value를 넣음
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
}
export default App;
컴포넌트가 사라졌을 때 무언가를 어떻게 실행하는지, 이 과정을 우리는 클린 업 (clean up) 이라고 표현한다.
클린 업을 하는 방법은 간단하다. useEffect 안에서 return 을 해주고 이 부분에 실행되길 원하는 함수를 넣으면 된다.
// src/App.js
import React, { useEffect } from "react";
const App = () => {
useEffect(()=>{
// 화면에 컴포넌트가 나타났을(mount) 때 실행하고자 하는 함수를 넣어주세요.
return ()=>{
// 화면에서 컴포넌트가 사라졌을(unmount) 때 실행하고자 하는 함수를 넣어주세요.
}
}, [])
return <div>hello react!</div>
};
export default App;
속세를 벗어나는 버튼 을 만들었고 버튼을 누르면 useNavigate에 의해서 /todos로 이동하면서 속세 컴포넌트를 떠날 것이다. 그러면서 화면에서 속세 컴포넌트가 사라질 것 이고, useEffect의 return 부분이 실행될 것이다.
// src/SokSae.js
import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
const 속세 = () => {
const nav = useNavigate();
useEffect(() => {
return () => {
console.log(
"안녕히 계세요 여러분! 전 이 세상의 모든 굴레와 속박을 벗어 던지고 제 행복을 찾아 떠납니다! 여러분도 행복하세요~~!"
);
};
}, []);
return (
<button
onClick={() => {
nav("/todos");
}}
>
속세를 벗어나는 버튼
</button>
);
};
export default 속세;