FrontEnd/React

리액트에서 ...state 와 prev => ...prev 의 차이

여행 가고싶다 2023. 4. 25. 15:49

리액트는 난해하다..



다음 두 가지 방법으로 상태를 업데이트할 수 있다.

 

  const [state1, setState1] = useState({
    id: '',
    name: '',
  });
  const [state2, setState2] = useState({
    id: '',
    name: '',
  });

  setState1({ ...state1, name: e.target.value });
  setState2((prevState2) => ({ ...prevState2, name: e.target.value }));

 

검색을 아무리 많이 해봐도 이 둘의 차이를 명확하게 짚어 주지 않아서 개인 프로젝트로 여러 가지 실험을 해봤다.

 

거의 동일한 기능이라고 봐도 무방하다.

 

하지만, 핵심적인 차이점은

 

이전상태를 고려하지않는다.
즉, 최신 값을 보장할 수 없다.

예를 들면,

// 첫번째 케이스 사용 예시
const [items, setItems] = useState([]);

// 새로운 항목 추가하기
const addItem = (newItem) => {
  // 이전 상태(prevState)를 고려하지 않음
  setItems([...items, newItem]);
};

 

하지만 이전 상태(prevState)를 고려해야 하는 경우, 예를 들어, 배열의 항목 수를 기반으로 계산하는 경우:

 

// 두번째 케이스 사용 예시
const [itemsCount, setItemsCount] = useState(0);
const [items, setItems] = useState([]);

// 항목 추가하기
const addItem = (newItem) => {
  setItems((prevState) => {
    // 이전 상태(prevState)를 고려하여 항목 수 계산
    const newItems = [...prevState, newItem];
    setItemsCount(newItems.length);
    return newItems;
  });
};

 

위의 코드에서 이전 상태를 고려하지 않으면 항목 수가 제대로 계산되지 않을 수 있다.

따라서 함수형 업데이트를 사용하면 예기치 못한 동작을 예방할 수 있다.

 

 


추가로 https://velog.io/@mh-yeo/React-prevState-in-setState 블로그에서 본 건데 너무 좋은 예제라 가져왔다.

 

  const [state, setState] = useState(0);
  const sumAll1 = () => {
    setState(state + 1);
    setState(state + 2);
    setState(state + 3);
    setState(state + 4);
  };
  const sumAll2 = () => {
    setState((prev) => prev + 1);
    setState((prev) => prev + 2);
    setState((prev) => prev + 3);
    setState((prev) => prev + 4);
  };

  return (
    <>
      <div>결과는 : {state}</div>
      <button type='button' onClick={sumAll1}>
        실행1 !
      </button>
      <button type='button' onClick={sumAll2}>
        실행2 !
      </button>
    </>
  );

1번을 실행하면 결과는 5가 나오고 2번을 실행하면 결과가 10이 나온다.

1번 실행결과
2번 실행결과

확실히 이전값을 보장받는 느낌이다.