State Vs. Prev

Front-end React

State vs. Prev

State란 리액트 컴포넌트에서 데이터를 담기 위한 상자라고 보면 좋다. 이 상자에 담긴 내용은 함수가 모두 끝나게 되면 화면에 렌더되게 된다. State 글에서 사용했던 Count incrementer 예제를 잠시 가져와보자.

// Model Counter example
const [ count, setCount ] = useState(0)

function increment(){
  setCount(count + 1)
}

return (
  <div>
    <div>{count}</div>
    <button onClick={increment}>Increment</button> 
  </div>
)

위 코드를 화면에 출력하면 버튼을 클릭할 때마다 카운터가 하나씩 증가하며 숫자 증가가 정상적으로 반영된다.

하지만, count를 n개씩 증가하기 위해 setCount를 여러번 호출하게 되면 의도하던 상황이 쉽게 발생하지 않는 것을 확인할 수 있다.

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

function handleClickIncrement() {
  setCount(count + 1); // 실제 count를 가져온다. count는 0이므로 0 + 1 = 1이 된다.
  setCount(count + 1); // 1이 state에 담겼지만 여전히 count는 0이므로 0 + 1 = 1이 된다.
  setCount(count + 1); // 1이 state에 담겼지만 여전히 count는 0이므로 0 + 1 = 1이 된다.
  setCount(count + 1); // 최종적으로 1이 state에 담겨 화면에 1이 반영된다.
  // count = 1이고, 리렌더가 된다.
}

return (
<div>
  <div>{count}</div>
  {/* Count 는 1이 된다 */}
  <button onClick={handleClickIncrement}>Increment</button>
</div>
);

위와 같은 로직에 따라 count를 4번 불렀음에도 count는 1씩만 증가하게 된다.

의도한대로 count 가 4개씩 증가하게 만드려면 prev라는 임시 저장공간을 사용하여 코드를 작성해야 한다.

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

function handleClickIncrementWithPrev() {
  setCount((prev) => prev + 1); // 임시 저장공간에서 count가 있는지 본다. 없으면 실제 count를 가져온다.
  setCount((prev) => prev + 1); // 임시 저장공간에 count = 1이 있다. 1 + 1 = 2 가 된다.
  setCount((prev) => prev + 1); // 임시 저장공간에 count = 2이 있다. 2 + 1 = 3 이 된다.
  setCount((prev) => prev + 1); // 임시 저장공간에 count = 3이 있다. 3 + 1 = 4 가 된다.
  // count = 4이고, 리렌더가 된다.
}

return (
<div>
  <div>{count}</div>
  {/* Count 는 4가 된다 */}
  <button onClick={handleClickIncrementWithPrev}>
  Increment With Prev
  </button>
</div>
);

이렇게 prev 를 사용하게 되면 임시 저장공간에 있는 값을 먼저 꺼내오고, 만약 임시 저장공간이 비어있다면 기본 state를 불러오게 된다.