setState 본격 해부

이주영·2023년 2월 10일
0
post-thumbnail

계기 🌱

React 라이브러리를 6개월간 사용하면서 아는 줄 알았으나 모르고 있었던 부분을 개발자 커뮤니티의 질문을 통해 알게 됐습니다.

What is the "함수형 업데이트"??

현재 제 디지털 가든의 함수형 업데이트 메모를 살펴보면

  • 작년 11월 24일에는 함수형 업데이트 방식을 활용하여 의존성 배열에 state가 담기지 않도록 한것이 핵심이라고 생각했고

  • 1월에는 함수형 업데이트의 핵심은 불변성을 지키기 위함이라고 생각했습니다.

  • 2월인 지금, 리액트 공식 문서 베타버전을 꼼꼼히 읽으면서 알게 된 것들을 정리하려고 합니다.

updater function을 사용하는 이유

setState(state => state + 1) // <-- updater function

updater function을 사용하는 이유는

"한번의 event", 즉 한번의 render동일한 상태가 여러번 업데이트된 것을 반영를 하기 위함입니다.

react's batching

간단하게 react의 batching을 정리해보면, 여러개의 상태를 한번에 묶어서 eventHandler의 모든 코드가 끝났을때 업데이트 해주는 리액트의 업데이트 방식입니다 이로 인해 불필요한 렌더링을 막을 수 있습니다.

예시

(updater function가 아닐때)

const [count, setCount] = useState(0);
console.log(count) // 1
return (
 <div className="App">
      <button
        onClick={() => {
          setCount(count + 1); // 0 + 1
          setCount(count + 1); // 0 + 1
		  setCount(count + 1); // 0 + 1
		  setCount(count + 1); // 0 + 1
        }}
      >
        {count}
      </button>
    </div>
)

마지막 setCount(count+1) 만 동작하는 것을 볼 수 있습니다.

  • 결과물

(updater function 일때 )

const [count, setCount] = useState(0);
console.log(count) // 4
return ( 
  <div className="App">
      <button
        onClick={() => {
          setCount((prev) => prev + 1); // 0 + 1
          setCount((prev) => prev + 1); // 1 + 1
          setCount((prev) => prev + 1); // 2 + 1
          setCount((prev) => prev + 1); // 3 + 1
        }}
      >
        {count}
      </button>
    </div>
)

updater function을 활용하면
함수형 업데이트를 사용하여 이전값을 토대로 +1을 해야 의도한 동작이 수행됩니다.

react beta공식 문서를 통해 간단히 이해해보자

If you pass a function as nextState, it will be treated as an updater function.

setState 함수 안에 callBack 함수를 인자에 넣을 경우, 바로 이전 상태 값을 바탕으로 새로운 값을 계산합니다.

💡 1일차 깨달음

callBack(함수에 파라미터로 들어가는 함수)함수는 비동기식 처리 방식을 수행합니다. setState안에 callBack인 화살표 함수 (prev => prev + 1)을 넣으면 비동기 처리가 끝나는 시점에서 함수를 호출하여 동기적으로 이전 함수가 끝나면 호출하여 값을 계산해줍니다.

💡 2일차 깨달음

useState은 동기적으로 실행되지만 리액트에서 상태를 업데이트 설계가 비동기적으로 되어있다는 것을 알게 됐습니다. 정리하자면 함수형 업데이트를 사용하는 이유는 동일한 state가 여러번의 업데이트된 것을 다음 렌더에 반영하기 위해서라고 생각합니다.

정리

  • state를 설정하여도 해당 랜더에는 반영이 되지 않고 다음 랜더에 적용되는 특징이 있습니다.
  • 리액트는 상태 업데이트를 eventHandler의 코드가 종료되면 실행한다. 이것을 batching이라고 합니다.
  • 한번의 이벤트에 동일한 상태를 여러번 업데이트를 하기 위해서 setState의 인자에 콜백함수를 넣어서 updater 함수를 만들어 사용합니다.

참고 자료

profile
https://danny-blog.vercel.app/ 문제 해결 과정을 정리하는 블로그입니다.

0개의 댓글