📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄

[React] useState 상태변화 함수의 매개변수로 기존 값 가져오기

두 함수의 차이는?

// #1
const insertData = useCallback((todo) => {
    let info = {
        seq: index.current,
        task: todo,
        date: new Date().toLocaleString().replace(/-/g, '.')
    }
    setData([info, ...data]);
    index.current++;
});

// #2
const insertData = useCallback((todo) => {
    setData((prevData) => {
        let info = {
            seq: index.current,
            task: todo,
            date: new Date().toLocaleString().replace(/-/g, '.')
        }
        index.current++;
        return [info, ...prevData];
    })
})

#1과 #2의 함수는 둘 다 useState를 통해 기존의 상태값을 수정하는 함수라는 점에서 공통점이 있다.

둘의 차이점은 상태변화 함수를 통해서 새로운 data 값을 기존의 상태값에 추가하는 방식에 있다.

#1은 상태변화 함수에 직접적으로 데이터를 집어넣는 방식으로 함수가 실행될 때마다 기존의 데이터를 모두 삭제한 뒤 새로운 데이터를 생성하고 있다.

반대로, #2는 상태변화 함수에 함수를 전달함으로써 기존 값을 매개변수로 전달해 #1처럼 삭제하고 생성하는 게 아닌 기존 값은 그대로 유지한 채 새로운 값만 추가하는 방식을 취하고 있다.

 

#1의 방식은 업데이트 시점이 명확하고 간편하게 상태값을 변경할 수 있다는 장점이 있지만, 상태값의 안정성 면에서는 조금 위험한 방법이다. 예를 들어, 비동기적인 상황에서 여러 번의 상태변화 함수의 호출이 발생하는 경우 호출된 순서대로 상태값이 정렬돼 있는 게 아닌 순서가 뒤죽박죽으로 엉켜있는 경우가 있을 수 있다.

 

#2의 경우에는 상태변화 함수가 상태값을 반환하기 때문에, 상태값의 안정성이 보장되며 최적화 면에서도 #1의 방식보다 뛰어나다고 할 수 있다. 따라서, #2의 방식으로 함수를 통해 상태값을 반환하는 방식을 사용하는 것을 추천한다.

 

상태변화 함수의 매개변수는 기존값이다.

const [data, setData] = useState([]);
const handleData = () => {
    setData((prevData) => {
        ...
    })
}

useState의 상태변화 함수에서 함수로 상태값을 변경한다면, 그 함수의 매개변수는 기존 상태값을 가리킨다.

이것은 useState Hook이 가지는 특징이며, 우리는 이 매개변수를 이용해 기존 상태값을 가져올 수 있다.

상태값을 교체하는 게 아닌 기존 상태값을 유지하는 상태라면 매개변수를 기존값으로 사용해보자.

 

같은 원리의 useReducer

const reducer = (state, action) => {
    switch (action.type) {
    	case 'increment':
            return { count: state.count + 1 };
    	case 'decrement':
            return { count: state.count - 1 };
    	default:
            return state;
    }
};

위 코드는 useReducer의 reducer이다. reducer는 매개변수로 stateaction을 가져오는데, 여기서 state가 바로 useState에서 매개변수로 받아왔었던 기존 상태값을 의미한다. (useState의 매개변수가 기존 상태값인 것처럼)

 

1. setData((prevData) => {...}) 여기서 prevData 매개변수는 기존 상태값을 의미한다.
2. 기존 상태값에 새로운 데이터를 추가할 때, 기존 상태값을 매개변수로 가져와서 사용하자.