swsnu / swppfall2019

31 stars 23 forks source link

[small tip/react] escape from asynchronous update of this.setState #206

Open coiger opened 4 years ago

coiger commented 4 years ago

React에서 this.setState로 component의 state를 변경하고자 할 때, 비동기적으로 업데이트되는 원리 때문에 한 박자씩 늦게 state가 업데이트되는, 바로 state update 반영이 되지 않는 상황을 겪어보셨다면 이 tip 방법을 한 번 사용해 보는 것도 좋을 것 같습니다!

그 방법은 this.setState의 인자에 객체 대신 함수를 넣어주는 것인데, 원래 state update를 this.setState({ mystate: this.state.mystate + 1 }); 이런 식으로 사용했었다면, this.setState(prevState => ({ mystate: prevState.mystate + 1 })); 이런 식으로 이전 state를 입력으로 받고, 다음 state를 return하는 함수를 넣어주는 것입니다.

위와 같은 방법으로 업데이트를 하면, 바로 state 값이 바뀌지 않던 상황이 해결되는 것을 볼 수 있습니다!

참고로, 함수를 인자로 넣어줄 때, 그 함수의 입력 값으로 이전 상태(prevState)말고, props도 넣어줄 수도 있습니다. state를 업데이트 할 때 props 값이 필요하다면, 사용할 수 있겠습니다. this.setState((prevState, props) => ({ ... })); 이런 식으로요!

ref : https://medium.com/@wisecobbler/using-a-function-in-setstate-instead-of-an-object-1f5cfd6e55d1

ktaebum commented 4 years ago

한 가지 첨언하자면 해당 내용은 React 공식 document https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous 에서도 확인할 수 있습니다

React may batch multiple setState() calls into a single update for performance.

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
coiger commented 4 years ago

오 감사합니다!