본 글은 벨로퍼트의 모던 자바스크립트를 바탕으로 작성되었습니다.
본문보기
useEffect라는 hook을 사용해 컴포넌트가 마운트 됐을 때 (처음 나타났을 때), 언마운트 됐을 때(사라질 때), 그리고 업데이트 될 때(특정 props가 바뀔 때) 특정 작업을 처리하는 방법에 대해 알아보자.
function User({ user, onRemove, onToggle }) {
useEffect(() => {
consol.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({users, onRemove, onToggle}) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
useEffect
를 사용 할 때에는 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열 (deps)을 넣습니다. 만약에 deps 배열을 비우게 된다면, 컴포넌트가 처음 나타날때에만 useEffect
에 등록한 함수가 호출됩니다.
그리고, useEffect
에서는 함수를 반환할 수 있는데 이를cleanup
함수라고 부른다. cleanup
함수는 useEffect
에 대한 뒷정리를 해준다고 이해하면 편하다. deps가 비어있는 경우에는 컴포넌트가 사라질때 cleanup
가 호출된다.
주로 마운트 시에 하는 작업들은 다음과 같은 사항들이 있다.
그리고 언마운트 시에 하는 작업들은 다음과 같은 사항들이 있다.
deps에 특정값을 넣게 된다면, 컴포넌트가 처음 마운트 될 때에도 호출이 되고, 지정한 값이 바뀔 때에도 호출이 된다. 그리고, deps 안에 특정 값이 있다면 언마운트시(맨처음)에도 호출이 되고, 값이 바뀌기 직전에도 호출이 된다.
import React, { useEffect } from 'react';
function User({ user, onRemove, onToggle}) {
useEffect(() => {
console.log('user 값이 설정됨');
console.log(user);
return () => {
console.log('user 가 바뀌기 전..');
console.log(user);
};
}, [user]);
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onREmove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default userList;
useEffect
안에서 사용하는 상태나, props가 있다면, useEffect
의 deps에 넣어주어야 한다. 그렇게 하는 것이 규칙이다.
만약 useEffect
안에서 사용하는 상태나 props를 deps
에 넣지 않게 된다면 useEffect
에 등록한 함수가 실행될 때 최신 Props/상태를 가리키지 않게 된다.
최신 상태를 계속 갱신하며 주시해야 하는 경우 값을 반드시 넣어주자!
deps 파라미터를 생략한다면, 컴포넌트가 리렌더링 될때마다 모든 자식 컴포넌트가 호출이 된다.
import React, { useEffect } from 'react';
function User({user, onRemove, onToggle }) {
useEffect(() => {
console.log(user);
});
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
참고로 리액트 컴포넌트는 기본적으로 부모컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링이 된다. 바뀐 내용이 없다 할지라도 말이다.
물론, 실제 DOM에 변화가 반영되는 것은 바뀐 내용이 있는 컴포넌트에만 해당한다. 하지만, Virtual DOM에는 모든걸 다 렌더링하고 있다.
나중에는, 컴포넌트를 최적화 하는 과정에서 기존의 내용을 그대로 사용하면서 Virtual DOM에 렌더링하는 리소스를 아낄 수 있다.
useEffect를 사용할때, 값이 변하는 것을 확인하려면 deps파라미터에 값을 반드시 넣어주자!