
여러 useEffect를 사용할 때 첫 번째 useEffect를 건너뛰는 방법
React를 사용해본 적이 있다면 useEffect 훅에 익숙할 것입니다. useEffect는 함수형 컴포넌트에서 데이터 가져오기, 이벤트 구독, DOM 업데이트와 같은 사이드 이펙트를 수행할 수 있게 해줍니다. 그러나 때로는 불필요한 작업을 피하기 위해 첫 번째 useEffect를 건너뛰어야 할 수 있습니다.
처음 해결책
첫 번째 useEffect를 건너뛰는 흔한 해결책은 useRef 훅을 사용하여 초기 렌더링을 추적하는 것입니다. 다음은 예제 코드입니다:
const isFirstRun = useRef(true);
useEffect(() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
console.log("Effect was run");
});
이 예제에서 isFirstRun 변수는 useRef 훅을 사용하여 true로 초기화됩니다. useEffect 내부에서 isFirstRun이 true인지 확인합니다. true인 경우 false로 설정한 다음 작업을 수행하지 않고 반환합니다. 이후의 렌더링에서는 조건 검사가 실패하여 이펙트가 실행됩니다.
여러 useEffect 처리
하지만 컴포넌트에 여러 useEffect가 있는 경우 어떻게 해야 할까요? 각 useEffect에 동일한 isFirstRun 접근 방식을 사용하면 원하는 대로 작동하지 않습니다. 하나의 useEffect가 반환되어도 초기 렌더링 시간에 다른 useEffect가 실행됩니다.
이를 해결하기 위한 한 가지 접근 방식은 “useMounted”라는 커스텀 훅을 생성하여 첫 번째 렌더링인지 연이어 다시 렌더링인지 추적하는 것입니다. 다음은 예제 코드입니다:
const { useState } = React;
function useMounted() {
const [isMounted, setIsMounted] = useState(false);
React.useEffect(() => {
setIsMounted(true);
}, []);
return isMounted;
}
function Comp() {
const [amount, setAmount] = useState(props.Item ? Item.Val : 0);
const [type, setType] = useState(props.Item ? Item.Type : "Type1");
const isMounted = useMounted();
useEffect(() => {
if (isMounted) {
props.OnAmountChange(amount);
}
}, [amount]);
useEffect(() => {
if (isMounted) {
props.OnTypeChange(type);
}
}, [type]);
return (
<>
// Type 선택을 위한 라디오 버튼 그룹
// Amount 설정을 위한 입력 필드
</>
);
}
이 예제에서는 useMounted 커스텀 훅을 사용하여 첫 번째 렌더링인지 여부를 확인합니다. isMounted 플래그를 사용하여 useEffect를 연이어 다시 렌더링할 때에만 조건부로 실행할 수 있게 됩니다.
이펙트를 결합하기
여러 useEffect의 로직을 결합하고자 한다면 그것도 가능합니다. 핵심은 각 이펙트를 독립적으로 취급하고 관련 상태를 변경하는지 확인하는 것입니다. 다음은 예제 코드입니다:
const Comp = () => {
const [amount, setAmount] = useState(null);
const [type, setType] = useState(null);
useEffect(() => {
if (amount !== null) {
props.onAmountChange(amount);
} else {
props.onAmountChange(0);
}
}, [amount]);
useEffect(() => {
if (type !== null) {
props.onTypeChange(type);
} else {
props.onTypeChange("Type1");
}
}, [type]);
return (
<>
// Type 선택을 위한 라디오 버튼 그룹
// Amount 설정을 위한 입력 필드
</>
);
};
이 접근 방식에서는 amount와 type 상태를 null로 초기화합니다. 값이 null이 아닌 경우, 각각의 props 메서드를 호출합니다. 이로써 사용자가 실제로 값을 설정하기 전까지는 props 메서드의 실행을 지연할 수 있으며, 사용자가 값을 기본값으로 되돌리는 경우도 처리할 수 있습니다.
결론
첫 번째 useEffect를 건너뛰는 것은 초기 렌더링 시 불필요한 작업을 피하고자 할 때 유용할 수 있습니다. useRef를 사용하거나 첫 번째 렌더링을 추적하기 위해 커스텀 훅을 생성함으로써 초기 렌더링인지 여부에 따라 useEffect를 선택적으로 실행할 수 있습니다. 여러 useEffect를 분리하거나 하나로 결합하더라도, 여러 useEffect를 처리하는 로직을 적응시킬 수 있습니다.