React 컴포넌트가 화면에 렌더링된 이후에
비동기로 처리되어야 하는 부수적인 효과들을 Side Effect라고 한다.
대표적인 예로
어떤 데이터를 가져오기 위해서 외부 API를 호출하는 경우,일단 화면에 렌더링할 수 있는 것들을 먼저 렌더링하고
실제 데이터는 비동기로 가져오는 것이 권장된다.
요청 즉시 1차 렌더링을 함으로써 연동하는 API가 응답이 늦어지거나 응답이 없을 경우에도 영향을 최소화 시킬 수 있어서 사용자 경험 측면에서 유리하기 빼문이다.
React Hooks가 나오기 전에는 클래스 컴포넌트의 componentDidMount()
나 componentDidUpdate()
함수와 같은 Life Cycle Hook함수를 사용해서 Side Effect 처리를 했다.
import React, { Component } from "react";
class UserListClass extends Component {
state = {
loading: true,
users: [],
};
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => this.setState({ users, loading: false }));
}
render() {
const { loading, users } = this.state;
if (loading) return <div>Loading...</div>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
}
loading
의 초기값 = true
이므로 Loading...
이라는 메세지가 나타난다. componentDidMount()
함수가 호출되면 loading
이 false
로 업데이트 되어 사용자 이름들이 나타난다.
클래스 기반 컴포넌트는 함수 기반 컴포넌트에 비해 복잡하다.
따라서 오류가 발생하기 쉽고 유지보수가 힘들다.
React Hooks에서 제공하는 useEffect() 함수를 사용해서 위의 클래스 기반 컴포넌트를 함수 기반으로 작성할 수 있다.
useEffect가 하는 일?
React에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야하는 지를 말한다.
React는 우리가 넘긴 함수('effect')를 기억했다가 DOM update를 수행한 이후에 불러낸다.
import React, { useState, useEffect } from "react";
function UserListFunction() {
const [loading, setLoading] = useState(true);
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((users) => {
setUsers(users);
setLoading(false);
});
});
if (loading) return <div>Loading...</div>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
실제 프로젝트에서 사용되는 복잡한 클래스 컴포넌트를 useState()를 사용해서 함수 컴포넌트로 리팩토링하면 진가를 확인할 수 있다.