react setState의 비동기 동작

차유림·2021년 11월 18일
0
// 상태 업데이트(객체 전달) 
// 함수 실행될때 +1 씩 증가
handleIncrease = () => {
  this.setState({
    counter: this.state.counter + 1
  });
  this.setState({
    counter: this.state.counter + 1
  });
};

// 상태 업데이트(함수 전달) 
// 함수 실행될때 +2 씩 증가
handleIncrease = () => {
    this.setState(state => ({
      counter: state.counter + 1
    }));
    this.setState(state => ({
      counter: state.counter + 1
    }));
  };

위 코드에서처럼 setState 함수를 사용할 때,
인자로 업데이트할 값을 넣어줄 수 있고
함수를 넘겨줄 수 도 있다.
두 방법의 차이점을 알아보자.

리액트 공식문서에 보면
setState()는 컴포넌트 state의 변경 사항을 대기열에 집어넣고,
React에게 해당 컴포넌트와 그 자식들이
업데이트된 state를 사용하여 다시 렌더링되어야 한다고 알린다고 나와있다.

setState()는 상태를 바로 변경하지 않고
상태변경을 요청하는 것이라고 생각하면 된다.

리액트에서는 성능이유로, 상태 변경이 바로 일어나지 않고
비동기적으로 업데이트 된다.
즉 컴포넌트에서의 상태변화를 일괄적으로 업데이트하거나
나중으로 미루거나 하기 때문에,
state가 즉시 변경됨을 보장하지 않는다.

이 때문에 state가 변경되고 무언가를 처리해야한다면,
setState(updater, callback)의 두번째 인자인 콜백함수를 사용하거나
componentDidUpdate(이걸 더 권장)를 사용해야 한다.

다시 돌아와서,
setState()는 비동기적으로 수행되기 때문에
한 함수내에서 여러번 호출된다면 일괄적으로 처리될 수 있다.
이는 Object.assign과 같은 결과를 가진다.

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)
  
// quantity 값은 계속 덮어쓰기 되어
// 가장 마지막 state.quantity + 1 이 적용됨  
// 이때는 state.quantity 값이 다 동일하기 때문에 
// 변경가 한번일어난 것으로 됨

따라서 state값을 기준으로 state값을 업데이트해야 한다면 updater함수를 사용해야한다.


this.setState((state) => {
  return {quantity: state.quantity + 1};
});

//this.setState((state, props) => {
//  return { counter: state.counter + props.step };
//});

updater 함수에서 state는 업데이트 시점에
컴포넌트가 가지는 state에 대한 참조로,
최신값임이 보장된다.
또한 updater 의 결과는 state에 얕게 병합(merge)된다.
(this.setState에서 변경될 상태값만 넣어줘도 되는 이유)

profile
🎨프론트엔드 개발자💻

0개의 댓글