프론트엔드 첫걸음

함수형 setState 업데이트 본문

개발 공부/React

함수형 setState 업데이트

차정 2022. 7. 14. 19:32

setState는 비동기적으로 작동한다.

이벤트 핸들러안에서 호출된 setState는 setState가 얼마나 많이 호출되었든 상관없이
이벤트가 끝날때 딱 한번 리렌더링 된다.
이는 불필요한 렌더링을 막아 리액트의 성능을 높인다.

 

 

이것을 오브젝트 컴포지션으로 설명할 수 있다.

setState가 여러번 호출되면 인자로 전달된 각 객체를 추출하여 단일 객체로 merge하고,
렇게 만들어진 단일 객체를 사용해서 상태를 업데이트 한다.

 

// state를 합치는 merging 작업
const resultObj = Object.assign({},  {a: 10}, {b: 20},{a: 30})

 

따라서 setState에 객체를 전달하여 이전상태에서 다음상태로 update하려고 하는것은 안전하지 않다.

 

 

 

setState는 객체뿐 아니라 함수도 인자로 받을 수 있다.

setState에 인자로 객체가 아닌 함수가 들어가면 setState는 호출된 순서대로 함수를 큐에 넣는다.

그 후에 큐의 각 함수를 호출하여 함수형 setState의 이전 상태를 전달하여 상태를 업데이트 하는 것이다.

 

리액트 내부동작을 흉내낸 코드로 이해해보자.

class User {
  state = { score: 0 };
  //let's fake setState
  setState(state, callback) {
    this.state = Object.assign({}, this.state, state);
    if (callback) callback();
  }
  // multiple functional setState call
  increaseScoreBy3() {
    this.setState((state) => ({ score: state.score + 1 })),
      this.setState((state) => ({ score: state.score + 1 })),
      this.setState((state) => ({ score: state.score + 1 }));
  }
}
const Justice = new User();

사용자가 increaseScoreBy3()하면 React는 여러 기능을 가진 setState를 큐에 넣는다.

//queue에 넣는 것을 흉내낸 updateQueue 배열
const updateQueue = [
  (state) => ({ score: state.score + 1 }),
  (state) => ({ score: state.score + 1 }),
  (state) => ({ score: state.score + 1 }),
];


// 재귀적으로 배열에 있는 함수를 실행하여 updateQueue의 함수를 순차적으로 실행한다.
function updateState(component, updateQueue) {
  if (updateQueue.length === 1) {
    return component.setState(updateQueue[0](component.state));
  }
  return component.setState(updateQueue[0](component.state), () =>
    updateState(component, updateQueue.slice(1))
  );
}
updateState(Justice, updateQueue);

 

 

즉, 안정적으로 이전상태에 기반한 상태 업데이트를 하고싶다면, 함수형 setState를 써야한다는 것이다.

//1. setState에 객체를 넘기는 방식
setUserInput({
  ...userInput,
  enteredTitle: event.target.value,
});


//2. setState에 함수를 넘기는 방식
setUserInput((prevState) => {
  return { ...prevState, enteredTitle: event.target.value };
});

 

1번 방법보다 2번 방법을 써야한다.

 

 

 


[출처]

https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b

https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973#48610973