웹사이트 검색

자바스크립트 - setState는 비동기이므로, 콜백 큐를 통해 실행되나요?


저는 React가 처음이고 setState가 내부적으로 어떻게 작동하는지 배우고 있었습니다. 그래서 이에 대해 몇 가지 질문을 하고 싶습니다. 첫째, setState는 항상 비동기적인가요? 만약 그렇지 않다면 일반적으로 어떤 상황에서 동기식으로 동작하나요? 둘째, setState에서 비동기 처리가 어떻게 발생하는지, 웹 API를 통해 실행되고 나서 콜백 큐로 넘어가는 방식인가요? 여러분, 이해가 안 되는 부분이 있다면 알려주세요. 정말로 여러분의 도움이 필요합니다.

답변 #1

네. 항상 비동기이며 결코 동기적이지 않습니다. 개발자들이 흔히 저지르는 실수는 이런 것입니다.

 handleEvent(newValue) {
   this.setState({ value: newValue }, () => {
      // you can get the updated state here
      console.log(this.state.value)
   })
   this.doSomething(newValue)
 }

 doSomething(newValue) {
   // this.state.value is still the old value
   if (this.state.value === newValue) {
      // blabla
   }
 }

그리고 상태가 업데이트되는 데 얼마나 시간이 걸릴지 결정할 수 없습니다.

답변 #2

React setState는 항상 비동기적인 것은 아니며, 상태 변경이 어떻게 트리거되었는지에 따라 다릅니다.

1) 동기적 - 만약 동작이 Reactjs 외부에서 이루어지거나 상태 변경이 타이머 또는 사용자에 의해 유발된 이벤트 핸들러에 의해 트리거되었다면, Reactjs는 업데이트를 일괄 처리할 수 없으며 상태를 즉시 변경해야 합니다.

2) 비동기 만약 상태 변경이 onClick에 의해 트리거된다면, Reactjs는 성능 향상을 위해 상태 업데이트를 배치할 수 있습니다.

작동하는 코드샌드박스 링크

그리고

참조 게시물

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  state = {
    counter: 0
  };
  componentDidMount() {
    // const intervalId = setInterval(this.updateState, 5000);
    // this.setState({intervalId: intervalId});
    this.counter.addEventListener("mousedown", this.updateState);
  }
  componentWillUnmount() {
    this.counter.removeEventListener("mousedown", this.updateState);
    // clearInterval(this.state.intervalId);
  }
  updateState = event => {
    console.log("= = = = = = = = = = = =");
    console.log("EVENT:", event ? event.type : "timer");
    console.log("Pre-setState:", this.state.counter);
    this.setState({
      counter: this.state.counter + 1
    });
    console.log("Post-setState:", this.state.counter);
  };
  render() {
    return (
      <div className="App">
        <span onClick={this.updateState} ref={elem => (this.counter = elem)}>
          Counter at {this.state.counter}
        </span>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

콘솔 로그

    = = = = = = = = = = = =
    EVENT: mousedown 
    Pre-setState: 
    0
    Post-setState: 
    1
    = = = = = = = = = = = = 
    EVENT: click 
    Pre-setState: 
    1
    Post-setState: 
    1

콘솔 로그에서 볼 수 있듯이, mousedown 이벤트 상태 변경은 즉시 반영되지만 onClick 변경은 비동기적이거나, 더 정확히 말하면 일괄 처리됩니다.

그래서 상태 변경이 비동기적일 것이라고 가정하고, 버그를 피하기 위해 콜백 핸들러를 사용하는 것이 더 낫습니다. 그리고 물론 콜백 안의 모든 것은 자바스크립트에서 이벤트 루프를 거치게 됩니다.

도움이 되길 바래!!!