React Component가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 칭한다. 함수가 실행되면서 함수 외부에 존재하는 값이나 상태를 변경시키는 등의 행위를 칭한다.
예를 들어, 키 입력을 듣고 입력된 데이터를 저장하는 것, Form의 유효성을 검사하는 것, http Request를 보내는 것, 브라우저 저장소에 무언가를 저장하는 것, 코드에서 타이머나 간격을 설정하는 것, 네트워크를 통해 데이터를 송신하는 것 등이 포함된다.
즉, 어떤 액션에 대한 응답으로 실행되는 액션이 있다면 그것은 Side-Effect이다.
React에는 Side Effect를 처리할 수 있는 useEffect()
함수를 제공한다.
useEffect(() => {...}, [ dependencies ])
useEffect에는 2가지 인자가 있다.
1.() => {...}
: 특정 의존성이 변할 때 컴포넌트의 평가가 이루어진 후에 실행되어야 하는 코드가 들어가는 곳 -> side effect 코드를 여기에 선언한다.
즉,render이후 동작하게 될 함수
를 넣는다.
[ dependencies ]
: effect의 의존성 코드가 들어가는 곳(즉, 여기에 들어가는 코드가 변할 때 side effect 코드가 실행된다.)
즉,동작 시점을 정할 수 있도록 하는 의존값을 가지고 있는 배열
을 넣는다.
간단히 말해서, effect 함수에서 사용하는 모든 "것들"을 추가해야 한다.
구성 요소(또는 일부 상위 구성 요소)가 다시 렌더링 되어 이러한 "것들"이 변경될 수 있는 경우, 그렇기 때문에 컴포넌트 함수에 정의된 변수나 상태, 컴포넌트 함수에 정의된 props 또는 함수는 종속성으로 추가되어야 한다.
다음의 예시 코드를 살펴보자.
import { useEffect, useState } from 'react';
let myTimer;
const MyComponent = (props) => {
const [timerIsActive, setTimerIsActive] = useState(false);
const { timerDuration } = props; // using destructuring to pull out specific props values
useEffect(() => {
if (!timerIsActive) {
setTimerIsActive(true);
myTimer = setTimeout(() => {
setTimerIsActive(false);
}, timerDuration);
}
}, [timerIsActive, timerDuration]);
};
이 예시에서,
timerIsActive
는 종속성으로 추가되었다.
왜냐하면 구성 요소가 변경될 때 변경될 수 있는 구성 요소 상태이기 때문이다.
(예: 상태가 업데이트되었기 때문에)
timerDuration
는 종속성으로 추가되었다.
왜냐하면 해당 구성 요소의 prop 값이기 때문이다
따라서 상위 구성 요소가 해당 값을 변경하면 변경될 수 있다.
(이 MyComponent 구성 요소도 다시 렌더링되도록 함).
setTimerIsActive
는 종속성으로 추가되지 않는다.
왜냐하면, 예외 조건이기 때문이다.(상태 업데이트 기능을 추가할 수 있지만 React는 기능 자체가 절대 변경되지 않음을 보장하므로 추가할 필요가 없다.)
myTimer
는 종속성으로 추가되지 않는다.
왜냐하면 구성 요소 내부 변수가 아니기 때문이다.
(즉, 어떤 상태나 prop 값이 아님)
setTimeout
은 종속성으로 추가되지 않는다.
왜냐하면 내장 API이기 때문이다. (브라우저에 내장)
React 및 구성 요소와 독립적이며 변경되지 않는다.
useEffect(() => {
console.log("I'm UseEffect!");
})
dependencies
에 아무런 값도 넣지 않으면, 모든 re-render 상황에서 useEffect()가 실행된다.(모든 컴포넌트 렌더링 주기 이후에 실행된다. 첫 렌더링도 포함.)
useEffect(() => {
console.log("I'm UseEffect!");
}, [])
dependencies
에 빈 배열을 넣는다면, 초기 렌더링될 때 1번만 useEffect()가 실행된다.
useEffect(() => {
console.log("I'm UseEffect!");
}, [ isLogin ])
dependencies
에 특정 값을 넣는다면, 특정 값이 변할 때만 useEffect()가 실행된다.
Cleanup
함수 란, useEffect Hook 내에서 return되는 함수이다.
컴포넌트가 사라질 때(컴포넌트가 재사용 될 때, unmount)
또는 특정 값이 변경되기 전에 실행할 작업
을 지정할 수 있다.
useEffect(() => {
// 실행할 함수
// clean-up 함수
return () => { ... }
}, [ dependencies ]);
즉, clean-up 함수는 다음 2가지 상황에서 사용할 수 있다.
1. 컴포넌트가 unmount될 때(컴포넌트가 재사용 될 때) :useEffect(() => {...}, [])
2. 특정 값을 변경하기 전 :useEffect(() => {...}, [특정 값])
Re-rendering -> Clean-up 코드 실행 -> 사이드 이펙트 내부 코드 수행
예시 코드를 보자.
useEffect(() => {
// 사이트 이펙트 내부 코드(실행시킬 함수)
setTimeout(() => {
console.log('Checking form validity!');
setFormIsValid(
enteredEmail.includes('@') && enteredPassword.trim().length > 6
);
}, 500);
// clean-up 함수
return () => {
console.log('CLEANUP');
};
}, [enteredEmail, enteredPassword]);
위 코드는, 이메일과 비밀번호를 입력하는 인풋을 감싸는 폼이 있고, 해당 인풋에 변화가 감지되면 수행되는 useEffect() 코드이다.