본문 바로가기
Web/React

useState의 setter함수와 함수형 업데이트

by 가나닩 2024. 4. 14.

React는 최적화를 위해 가까운곳에서 여러개의 state변화가 일어날경우 이를 일괄처리하여 최종결과를 렌더링해준다. 이를 React의 automatic batching이라고한다. 개발자의 의도대로 실행이 완료되지 않은채 렌더링이 진행되거나 너무 많은 수의 렌더링이 진행되어 성능이 저하되는것을 막기위한 기능이다.

 

하지만 automatic batching 기능을 모른채로 개발을 하다보면 예상치못한 문제를 만날 수 있다.

 

직접적 상태 업데이트

const [count, setCount] = useState(0);

    const onClick = () => {
        setCount(count + 1);
        setCount(count + 1);
        setCount(count + 1);
    };

    return (
        <div>
            <div onClick={() => {onClick()}}>
                {count}
            </div>
        </div>
    );

 

count라는 state를 표시하고 숫자를 클릭하면 setter를 통해 숫자가 3번 증가하도록 했다.

내용만 보면 초기값 0을 다음으로 클릭할때마다 3, 6, 9, 12가 표시되어야 할것 같지만 1,2,3,4로 한개씩만 증가하게된다.

 

 

함수형 상태 업데이트

const [count, setCount] = useState(0);

    const onClick = () => {
        setCount((prev) => prev + 1);
        setCount((prev) => prev + 1);
        setCount((prev) => prev + 1);
    };

    return (
        <div>
            <div onClick={() => {onClick()}}>
                {count}
            </div>
        </div>
    );

 

setCount의 내부만 함수형으로 변경했다. 이렇게 실행할경우 의도한대로 3,6,9,12가 출력되는것을 확인할 수 있다.

 

 

원인

두 방식은 React에 setCount를 예약하고 실행하는것은 동일하지만 인수로 전달받은 값을 사용하는지, 함수를 직접 실행하는지의 차이가 있다.

직접 상태 업데이트는 setCount의 실행이 예약될 당시의 상태값을 가지고 예약된다. 따라서 여러번의 setCount를 실행하더라도 모든 setCount는 동일한 상태값을 이미 할당받은 상태이다. setCount의 매 실행마다 0을 1로 변경하는것을 반복하게 되는것이다.

하지만 함수형 업데이트 방식은 인수로 전달받은 값을 사용하지 않고 함수의 실행만을 예약해두었다가 함수가 실행될때 상태값을 가져와서 사용한다. 상태의 최신성을 보장받을수 있는 방식이다.

 

 

결론

useEffect 내부에서 여러번의 API 호출이 있거나 특정 함수에서 여러번의 state 변경이 이루어지는 등의 경우 React의 해당 속성을 잘 파악해서 사용해야한다. 하나의 setter로 줄일 수 있는 내용은 가능한 줄여 의도치않은 결과를 방지하는 등 여러가지 해결방법을 사용할 수 있다.