[리액트를 다루는 기술 - 김민준] 책을 일부 참고했습니다.
즉, useEffect는 클래스형 컴포넌트의
세 가지 라이프사이클 메서드가 합쳐진 형태로 보면 된다.
위 메서드들의 기능을 바탕으로하여 useEffect 사용법을 알아보자.
우선 예시코드가 필요하다.
import React, { useEffect, useState } from "react";
const Info = () => {
const [name, setName] = useState("");
useEffect(() => {
console.log("렌더링 완료");
console.log({ name });
});
const onChangeName = (e) => {
setName(e.target.value);
};
return (
<div>
<input
value={name}
onChange={onChangeName}
/>
<div>
<b>{name}</b>님, 반가워요!🙋🏻♀️
</div>
</div>
);
};
export default Info;
input 창에 이름을 입력하면 이름을 보여주는 Info 컴포넌트를 만들어 주었다.
예시 코드의 결과 사진을 보면 렌더링될 때마다 name의 값이 출력되고 있는 것을 볼 수 있다.
클래스 컴포넌트의 componentDidMount처럼 화면에 맨 처음 렌더링될 때만 실행하고 싶을때는 어떻게하면 좋을까?
방법 : useEffect 함수의 두 번째 파라미터로 비어 있는 배열을 넣어주면 된다.
useEffect(() => {
console.log("마운트될 때만 실행");
console.log({ name });
},[]);
위 코드를 수정해주었다. 결과를 살펴보자.
컴포넌트가 처음 나타날 때만 콘솔에 문구가 찍힌 것을 볼 수 있다!
클래스형 컴포넌트에서는 componentDidUpdate를 사용해서 특정 값이 업데이트될 때 일어나는 일을 다음과 같이 처리해줄 수 있다.
componentDidUpdate(prevProps, prevState) {
if (prevState.name !== this.state.name) {
console.log("name 값이 없데이트 되었을 때");
console.log(
`이전 Name : ${prevState.name}, 현재 Name : ${this.state.name}`
);
}
}
이것을 useState로 구현하면 다음과 같다.
useEffect(() => {
console.log("name 값이 없데이트 되었을 때");
console.log({ name });
}, [name]);
짠! 엄청 간결해졌다.
name 값이 변경될 때마다 로그에 찍히는 것을 확인할 수 있다.
클래스형 컴포넌트에서는 componentWillUnmount 함수를 사용해서 컴포넌트가 언마운트되기 전의 동작들을 정의해주었다.
Hooks에서는 컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떤 작업을 수행하고 싶으면 useEffect의 뒷정리 함수를 반환해주면 된다.
다음과 같이 useEffect 함수를 작성해보자.
useEffect(() => {
console.log("name 값 업데이트..");
console.log({ name });
return () => {
console.log("뒷정리하기");
console.log({ name });
};
});
이제, 컴포넌트가 언마운트 됐을때 뒷정리 함수가 반환되는 것을 확인해보자.
이를 확인하기 위해서 app.js 코드를 약간 수정해줘야 한다.
App.js
import React, { useState } from "react";
import Info from "./Info.js";
const App = () => {
const [visible, setVisible] = useState(false);
return (
<div>
<button
onClick={() => {
setVisible(!visible);
}}
>
{visible ? "당장 숨겨" : "보여줘.."}
</button>
<hr />
{visible && <Info />}
</div>
);
};
export default App;
버튼을 눌러서 우리가 만든 Info 컴포넌트를 숨기고 보여주는게 가능하도록 만들어 주었다.
이제 브라우저에서 실행 결과를 살펴보자!!
처음엔 아무것도 안보여준다. 보여줘.. 버튼을 눌러보자.
버튼을 누르자 컴포넌트가 나타나면서 useEffect 함수가 실행된 것을 볼 수 있다.
당장 숨겨보자.
버튼을 누르자 컴포넌트가 사라지고 뒷정리 함수가 실행된 것을 볼 수 있다.
그럼 이번에 이름을 입력해보자.
이런! 렌더링될 때마다 뒷정리 함수가 계속 나타나고 있다.
오직 언마운트될 때만 뒷저일 함수를 호출하고 싶다면 useEffect의 두 번째 파라미터에 배열을 넣으면 된다.
useEffect(() => {
return () => {
console.log("뒷정리하기");
console.log({ name });
};
},[]);
이번 포스팅을 하는 과정에서 Hooks 함수와 클래스 컴포넌트의 라이프사이클 함수를 비교하기 위해 두 경우의 코드를 모두 작성했다.
함수형과 클래스형을 비교하고 싶으면 아래 코드를 참고해보자!
import React, { useEffect, useState } from "react";
const Info = () => {
const [name, setName] = useState("");
useEffect(() => {
console.log("마운트될 때만 실행");
console.log({ name });
return () => {
console.log("뒷정리하기");
console.log({ name });
};
}, []);
useEffect(() => {
console.log("name 값이 없데이트 되었을 때");
console.log({ name });
}, [name]);
const onChangeName = (e) => {
setName(e.target.value);
};
return (
<div style={{ padding: "1rem" }}>
<input
style={{ marginBottom: "1rem" }}
value={name}
onChange={onChangeName}
/>
<div>
<b>{name}</b>님, 반가워요!🙋🏻♀️
</div>
</div>
);
};
export default Info;
import React, { Component } from "react";
class InfoClass extends Component {
state = {
name: "",
};
componentDidMount() {
console.log("마운트 될 때만 실행");
console.log(this.state);
}
componentDidUpdate(prevProps, prevState) {
if (prevState.name !== this.state.name) {
console.log("name 값이 없데이트 되었을 때");
console.log(
`이전 Name : ${prevState.name}, 현재 Name : ${this.state.name}`
);
}
}
componentWillUnmount() {
console.log("언마운트 될 때 실행");
console.log(this.state);
}
onChangeName = (e) => {
this.setState({
name: e.target.value,
});
};
render() {
const { name } = this.state;
return (
<div style={{ padding: "1rem" }}>
<input
style={{ marginBottom: "1rem" }}
value={name}
onChange={this.onChangeName}
/>
<div>
<b>{name}</b>님, 반가워요!🙋🏻♀️
</div>
</div>
);
}
}
export default InfoClass;