이 글은 velopert님의 벨로퍼트와 함께하는 모던 리액트를 참고하여 쓴 글 입니다.
useEffect란?
- 컴포넌트가 마운트 됐을때(처음 나타났을 때), 언마운트 됐을때(사라질 때), 업데이트 됐을때(특정 props가 바뀔 때) 특정 작업을 처리 한다.
- React컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 Side Effect라고 하는데, 이를 함수형으로 사용할수 있게 하는 hook이다.
마운트 시에 주로 하는 작업
props
로 받은 값을 컴포넌트의 로컬 상태로 설정- 외부 API 요청 (REST API 등)
- 라이브러리 사용 (D3, Video.js 등...)
- setInterval 을 통한 반복작업 혹은 setTimeout 을 통한 작업 예약
언마운트시에 주로 하는 작업
- setInterval, setTimeout 을 사용하여 등록한 작업들 clear 하기 (clearInterval, clearTimeout)
- 라이브러리 인스턴스 제거
사용법
useEffect
를 사용할 때, 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열(deps
)을 넣는다.
deps
에 빈배열: 처음에만 함수 호출, 컴포넌트가 사라질때 호출deps
에 의존값 존재 : 처음과 지정값이 변경될 때 호출deps
가 아예 없는 경우 : 컴포넌트가 리렌더링 될 때마다 호출
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
deps가 빈배열 인경우
- 첫 렌더링시에만 호출이 되고, 리렌더링 될때는 호출이 되지 않는다.
useEffect
에서 함수를 반환 할 수 있는데, 이를cleanup
함수라고 부른다.deps
가 빈배열인 경우에는 컴포넌트가 사라질 때cleanup
함수가 호출된다.
UserList.js
import React, { useEffect } from 'react';
function User({ user, onRemove, onToggle }) {
useEffect(() => { // useEffect 선언
console.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;
user
의 값이 마운트 될때와 삭제 될때는 useEffect
가 호출되지만, 클릭을 통해서 값이 수정될때(리렌더링)시에는 호출되지 않는 모습이다.
deps에 특정 값이 있는 경우
- 처음 마운트시, 지정한 값이 수정되기전, 수정된 후, 언마운트시 호출이 된다.
UserList.js
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;
deps
가 빈배열 일때와 다르게, user의 값이 리렌더링 전, 후에도 useEffect가 호출이 된다.
deps 파라미터가 생략된 경우
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;
deps가 생략된 경우, 리렌더링 혹은 삭제시 컴포넌트가 리렌더링 될 떄마다 호출이 된다.
정리
useEffect
- 함수이다
- 첫번째 인자는 함수, 두번째 인자는 배열(주로 deps 라고 칭한다.)이 들어간다.
cleanup 함수
- useEffect 안에서 return 할 때 실행된다.
- useEffcet의 뒷정리를 한다. -> state에서 값 지울때 실행됨
deps
- deps 에 특정값을 넣게 되면, 컴퍼넌트가 마운트 될 때, 지정한 값이 업데이트 될 때 useEffect 실행된다.
- deps에 값이 없다면 useEffect가 최신 값을 가리키지 않게 된다.
- deps에 값이 없다면 컴포넌트가 리렌더링 될 때마다 호출이 된다.
- deps에 값을 넣는것을 기본이라고 생각하는게 좋다.
반응형