useEffect
2023-09-04
ReactHooks
Table of Contents
useEffect가 나오게 된 배경
- 클래스형 컴포넌트에서 함수형 컴포넌트로 바뀔 때 클래스형 컴포넌트의 강점인 생명주기(라이프사이클)과 상태값 관리를 Hook이란 개념으로 도입하게 되면서 생명주기를 useEffect라는 Hook으로 관리하게 되었습니다.
1. 프로젝트 세팅 React + TS + Vite
$ npm init vite@latest React-UseEffect -- --template react-ts
$ cd React-UseEffect
$ npm i
/src/main.tsx
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root")!).render(
// <React.StrictMode>
<App />
// </React.StrictMode>,
);
- React StrictMode를 끄고 하겠습니다. 두번 렌더링이 되어 콘솔이 지저분해집니다.
2. useEffect 사용해보기
- 리액트 생명주기의 큰 틀
- mount → updating → unmounting
- mount → updating → unmounting
Mount의 개념
- 컴포넌트가 처음으로 DOM에 추가되는 초기 과정
Updating의 개념
- 컴포넌트의 상태나 속성이 변경되어 화면을 업데이트해야 할 때 발생하는 과정
/src/App.tsx
import "./App.css";
import { useState } from "react";
import Mount from "./Mount";
import Updating from "./Updating";
function App() {
const [isMount, setIsMount] = useState<boolean>(false);
function onClickHandler(event: React.MouseEvent) {
event.preventDefault();
setIsMount((prev) => !prev);
}
return (
<main>
<button onClick={onClickHandler}>{isMount ? "mount" : "render"}</button>
{isMount ? <Mount /> : <Updating />}
</main>
);
}
export default App;
- isMount가 true면 Mount 컴포넌트 마운트, 아니면 Updating 컴포넌트 마운트가 됩니다.
Mounting & unMounting
- useEffect로 mounting과 unmounting 주기를 관리하는 방법에 대해서 알아봅니다.
/src/Mount.tsx
import { useEffect } from "react";
const MountUnMount = () => {
useEffect(() => {
console.group("Mount");
console.log("useEffect(() => {},[])");
console.log("마운트 될 때에 실행");
console.groupEnd();
return () => {
console.group("UnMount");
console.log("return () => {}");
console.log("마운트가 해제될 때 실행");
console.groupEnd();
};
}, []);
return <div>Mount!</div>;
};
export default MountUnMount;
- mounting입니다. useEffect에 빈 배열을 넣어주면 mounting시에 실행됩니다.
- mounting이 되면 DOM에 접근할 수 있습니다.
- unmounting입니다. useEffect에 return과 실행시킬 함수를 할당하면 unmounting시 실행됩니다.
- unmounting시에 접근할 수 있는 return 함수를 clean-up 함수라고 명명하고 있습니다.
updating
- useEffect로 updating 주기를 관리하는 방법에 대해서 알아봅니다.
/src/Updating.tsx
import React, { useEffect, useState } from "react";
import UpdateChild from "./UpdateChild";
const Updating = () => {
const [state, setState] = useState("state");
useEffect(() => {
console.group("Updating, 첫 렌더링 시 실행된다.");
console.log(`useEffect(() => {}, [state])`);
console.log(`Updating state 값이 업데이트 되었습니다 ::: ` + state);
console.groupEnd();
return () => {
console.log(`return () => {}`);
console.log(`Updating 컴포넌트가 언마운트 되었습니다 ::: ` + state);
};
}, [state]);
useEffect(() => {
console.log(`Updating Component re-rendering`);
});
function onChangeHandler(event: React.ChangeEvent<HTMLInputElement>) {
event.preventDefault();
setState(event.target.value);
}
return (
<div>
<input type='text' onChange={onChangeHandler} value={state} />
<div>{state}</div>
<UpdateChild />
</div>
);
};
export default Updating;
- 처음 실행될 때와 배열 안에 넣은 값이 있으면(useState) 그 값이 변경됨에 따라 updating이 발생합니다.
- unmount의 동작은 같습니다.
- 의존성 배열이 없다면 컴포넌트가 updating을 할때마다 호출됩니다.
자식요소 updating
/src/Updating.tsx
import React, { useEffect } from "react";
const UpdateChild = () => {
useEffect(() => {
console.group("자식 컴포넌트");
console.log("자식 컴포넌트도 리렌더링 되고 있어요.");
console.groupEnd();
});
return <div></div>;
};
export default UpdateChild;
- 자식요소도 부모요소에 영향을 받는다. 같이 리렌더링 되는 모습입니다.