Programing

Sync 대신 reactjs Async에서 setState가 사용되는 이유는 무엇입니까?

lottogame 2020. 8. 14. 08:14
반응형

Sync 대신 reactjs Async에서 setState가 사용되는 이유는 무엇입니까?


this.setState()모든 구성 요소의 반응 함수가 비동기 적이 거나 호출 된 함수가 완료된 후에 호출 된다는 것을 방금 발견 했습니다.

이제이 블로그를 검색하고 찾았습니다 ( setState () State Mutation Operation May Be Synchronous In ReactJS )

여기서 그는 setState상태 변경이 트리거 된 방법에 따라 async (스택이 비어있을 때 호출 됨) 또는 sync (호출되는 즉시 호출 됨) 임을 발견했습니다 .

이제이 두 가지는 소화하기 어렵습니다

  1. 블로그에서 setState함수는 함수 내부에서 호출 updateState되지만 함수 를 트리거 한 updateState것은 호출 된 함수가 알 수있는 것이 아닙니다.
  2. setStateJS가 단일 스레드 언어이고이 setState가 WebAPI 또는 서버 호출이 아니므로 JS 스레드에서만 수행해야하므로 비 동기화하는 이유는 무엇입니까? Re-Rendering으로 인해 모든 이벤트 리스너 및 항목이 중지되지 않도록이 작업을 수행하고 있거나 다른 디자인 문제가 있습니다.

상태 값이 업데이트 된 후 함수를 호출 할 수 있습니다.

this.setState({foo: 'bar'}, () => { 
    // Do something here. 
});

또한 한 번에 업데이트 할 상태가 많은 경우 모두 동일한 내에서 그룹화합니다 setState.

대신에:

this.setState({foo: "one"}, () => {
    this.setState({bar: "two"});
});

다음과 같이하십시오.

this.setState({
    foo: "one",
    bar: "two"
});

1) setState작업은 비동기 적이며 성능 향상을 위해 일괄 처리됩니다. 이것은의 문서에 설명되어 setState있습니다.

setState ()는 this.state를 즉시 변경하지 않지만 보류 상태 전환을 만듭니다. 이 메서드를 호출 한 후 this.state에 액세스하면 잠재적으로 기존 값을 반환 할 수 있습니다. setState에 대한 호출의 동기 작업이 보장되지 않으며 성능 향상을 위해 호출이 일괄 처리 될 수 있습니다.


2) JS가 단일 스레드 언어이고 이것은 setStateWebAPI 또는 서버 호출이 아니기 때문에 왜 setState를 비동기로 만들 까요?

이는 setState상태를 변경하고 다시 렌더링 하기 때문 입니다. 이것은 비용이 많이 드는 작업 일 수 있으며이를 동기식으로 만들면 브라우저가 응답하지 않을 수 있습니다.

따라서 setState 호출은 더 나은 UI 경험과 성능을 위해 비동기식이며 일괄 처리됩니다.


이 질문이 오래되었다는 것을 알고 있지만 저를 포함하여 오랫동안 많은 reactjs 사용자에게 많은 혼란을 가져 왔습니다. 최근에 Dan Abramov (react 팀의)는 왜의 특성 setState이 비동기 인지에 대한 훌륭한 설명을 작성했습니다 .

https://github.com/facebook/react/issues/11527#issuecomment-360199710

setState비동기식을 의미하며 Dan Abramov의 링크 된 설명에 그 이유가 몇 가지 있습니다. 이것은 항상 비동기 적이라는 것을 의미하지는 않습니다. 그것은 주로 동기 적이라는 것에 의존 할 수 없다는 것을 의미합니다 . ReactJS는 상태를 변경하는 시나리오에서 많은 변수를 고려하여 를 실제로 업데이트하고 구성 요소를 다시 렌더링해야하는 시기를 결정 합니다. 이를 보여주는 간단한 예 는 사용자 작업에 대한 반응으로 호출하면이 (가) 즉시 업데이트 될 것이므로 (다시 말씀 드리지만, 믿을 수는 없지만) 사용자가 지연을 느끼지 않을 것입니다. ,하지만 전화하면state
setStatestatesetState ajax 호출 응답 또는 사용자에 의해 트리거되지 않은 다른 이벤트에 대한 반응으로 사용자가이 지연을 실제로 느끼지 않을 것이므로 약간의 지연으로 상태가 업데이트 될 수 있으며 대기하여 성능이 향상됩니다. 여러 상태 업데이트를 함께 일괄 처리하고 DOM을 더 적게 다시 렌더링합니다.


여기에 좋은 기사 https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md

// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3

Solution
this.setState((prevState, props) => ({
  count: prevState.count + props.increment
}));

또는 콜백 전달 this.setState ({.....},callback)

https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b


일부 구성 요소에서 카운터를 증가한다고 상상해보십시오.

  class SomeComponent extends Component{

    state = {
      updatedByDiv: '',
      updatedByBtn: '',
      counter: 0
    }

    divCountHandler = () => {
      this.setState({
        updatedByDiv: 'Div',
        counter: this.state.counter + 1
      });
      console.log('divCountHandler executed');
    }

    btnCountHandler = () => {
      this.setState({
        updatedByBtn: 'Button',
        counter: this.state.counter + 1
      });
      console.log('btnCountHandler executed');
    }
    ...
    ...
    render(){
      return (
        ...
        // a parent div
        <div onClick={this.divCountHandler}>
          // a child button
          <button onClick={this.btnCountHandler}>Increment Count</button>
        </div>
        ...
      )
    }
  }

There is a count handler attached to both the parent and the child components. This is done purposely so we can execute the setState() twice within the same click event bubbling context, but from within 2 different handlers.

As we would imagine, a single click event on the button would now trigger both these handlers since the event bubbles from target to the outermost container during the bubbling phase.

Therefore the btnCountHandler() executes first, expected to increment the count to 1 and then the divCountHandler() executes, expected to increment the count to 2.

However the count only increments to 1 as you can inspect in React Developer tools.

This proves that react

  • queues all the setState calls

  • comes back to this queue after executing the last method in the context(the divCountHandler in this case)

  • merges all the object mutations happening within multiple setState calls in the same context(all method calls within a single event phase is same context for e.g.) into one single object mutation syntax (merging makes sense because this is why we can update the state properties independently in setState() in the first place)

  • and passes it into one single setState() to prevent re-rendering due to multiple setState() calls (this is a very primitive description of batching).

Resultant code run by react:

this.setState({
  updatedByDiv: 'Div',
  updatedByBtn: 'Button',
  counter: this.state.counter + 1
})

To stop this behaviour, instead of passing objects as arguments to the setState method, callbacks are passed.

    divCountHandler = () => {
          this.setState((prevState, props) => {
            return {
              updatedByDiv: 'Div',
              counter: prevState.counter + 1
            };
          });
          console.log('divCountHandler executed');
        }

    btnCountHandler = () => {
          this.setState((prevState, props) => {
            return {
              updatedByBtn: 'Button',
              counter: prevState.counter + 1
            };
          });
      console.log('btnCountHandler executed');
    }

After the last method finishes execution and when react returns to process the setState queue, it simply calls the callback for each setState queued, passing in the previous component state.

This way react ensures that the last callback in the queue gets to update the state that all of its previous counterparts have laid hands on.


You can use the following wrap to make sync call

this.setState((state =>{
  return{
    something
  }
})


Yes, setState() is asynchronous.

From the link: https://reactjs.org/docs/react-component.html#setstate

  • React does not guarantee that the state changes are applied immediately.
  • setState() does not always immediately update the component.
  • Think of setState() as a request rather than an immediate command to update the component.

Because they think
From the link: https://github.com/facebook/react/issues/11527#issuecomment-360199710

... we agree that setState() re-rendering synchronously would be inefficient in many cases

Asynchronous setState() makes life very difficult for those getting started and even experienced unfortunately:
- unexpected rendering issues: delayed rendering or no rendering (based on program logic)
- passing parameters is a big deal
among other issues.

Below example helped:

// call doMyTask1 - here we set state
// then after state is updated...
//     call to doMyTask2 to proceed further in program

constructor(props) {
    // ..

    // This binding is necessary to make `this` work in the callback
    this.doMyTask1 = this.doMyTask1.bind(this);
    this.doMyTask2 = this.doMyTask2.bind(this);
}

function doMyTask1(myparam1) {
    // ..

    this.setState(
        {
            mystate1: 'myvalue1',
            mystate2: 'myvalue2'
            // ...
        },    
        () => {
            this.doMyTask2(myparam1); 
        }
    );
}

function doMyTask2(myparam2) {
    // ..
}

Hope that helps.

참고URL : https://stackoverflow.com/questions/36085726/why-is-setstate-in-reactjs-async-instead-of-sync

반응형