React 프로젝트를 진행하다 보면 useEffect를 사용할 때 종속성 배열에 대해 정확히 이해하는 것이 매우 중요하다. 아래의 두 코드 예제는 useEffect의 종속성 배열 설정에 따라 작동 방식이 어떻게 달라지는지를 보여준다.
1번 코드
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { charWindAndPickAtom } from "../../../atoms";
function CharacterInfo() {
const { characterName } = useParams();
const charWindAndPick = useRecoilValue(charWindAndPickAtom);
const [pickNum, setPickNum] = useState(0);
let newCharWindAndPick = [...charWindAndPick];
useEffect(() => {
const pickRankIndex = newCharWindAndPick
.sort((a, b) => Number(a.pickRate) - Number(b.pickRate))
.findIndex((item) => item.characterName === characterName);
setPickNum(pickRankIndex);
}, [newCharWindAndPick, setPickNum]);
}
2번 코드
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { charWindAndPickAtom } from "../../../atoms";
function CharacterInfo() {
const { characterName } = useParams();
const charWindAndPick = useRecoilValue(charWindAndPickAtom);
const [pickNum, setPickNum] = useState(0);
useEffect(() => {
let newCharWindAndPick = [...charWindAndPick];
const pickRankIndex = newCharWindAndPick
.sort((a, b) => Number(a.pickRate) - Number(b.pickRate))
.findIndex((item) => item.characterName === characterName);
setPickNum(pickRankIndex);
}, [charWindAndPick, setPickNum]);
}
1번 코드와 2번 코드의 가장 큰 차이점은 useEffect의 종속성 배열과 newCharWindAndPick의 정의 위치이다.
newCharWindAndPick의 정의 위치:
1번 코드에서는 newCharWindAndPick이 useEffect 바깥에 정의되어 있다.
이는 useEffect가 실행될 때마다 새로운 배열이 생성되지 않도록 보장한다.
2번 코드에서는 newCharWindAndPick이 useEffect 내부에 정의되어 있다.
이는 charWindAndPick이 변경될 때마다 useEffect가 실행되고 새로운 배열이 생성된다.
useEffect의 종속성 배열:
1번 코드에서는 newCharWindAndPick과 setPickNum을 종속성 배열에 포함하여, 이 값들이 변경될 때마다 useEffect가 실행된다.
2번 코드에서는 charWindAndPick과 setPickNum을 종속성 배열에 포함하여, 이 값들이 변경될 때마다 useEffect가 실행된다.
2번 코드에서는 characterName이 변경되어도 useEffect가 재실행되지 않기 때문에 pickNum이 업데이트되지 않는다.
반면에, 1번 코드는 characterName이 변경될 때 newCharWindAndPick이 변경되면서 useEffect가 재실행되어 pickNum이 올바르게 업데이트된다.
2번 코드의 useEffect 종속성 배열에 characterName을 추가하고, newCharWindAndPick을 useEffect 바깥으로 이동하여 한 번만 정의되도록 해야 한다.
수정된 2번 코드
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { charWindAndPickAtom } from "../../../atoms";
function CharacterInfo() {
const { characterName } = useParams();
const charWindAndPick = useRecoilValue(charWindAndPickAtom);
const [pickNum, setPickNum] = useState(0);
useEffect(() => {
let newCharWindAndPick = [...charWindAndPick];
const pickRankIndex = newCharWindAndPick
.sort((a, b) => Number(a.pickRate) - Number(b.pickRate))
.findIndex((item) => item.characterName === characterName);
setPickNum(pickRankIndex);
}, [charWindAndPick, characterName, setPickNum]);
}
이렇게 하면 characterName이 변경될 때마다 useEffect가 재실행되어 pickNum이 올바르게 업데이트된다.