Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么reactjs中的setState是异步的而不是同步的?_Javascript_Multithreading_Asynchronous_Reactjs - Fatal编程技术网

Javascript 为什么reactjs中的setState是异步的而不是同步的?

Javascript 为什么reactjs中的setState是异步的而不是同步的?,javascript,multithreading,asynchronous,reactjs,Javascript,Multithreading,Asynchronous,Reactjs,我刚刚发现,在reactthis.setState()中,任何组件中的函数都是异步的,或者是在调用它的函数完成后调用的 现在我搜索并找到了这个博客() 在这里,他发现setState是异步的(堆栈为空时调用)或同步的(调用后立即调用),这取决于状态更改的触发方式 现在这两件事很难消化 在博客中,setState函数是在函数updateState中调用的,但是触发updateState函数的不是被调用函数所知道的 为什么他们要使setState异步,因为JS是单线程语言,而这个setState不是

我刚刚发现,在react
this.setState()
中,任何组件中的函数都是异步的,或者是在调用它的函数完成后调用的

现在我搜索并找到了这个博客()

在这里,他发现
setState
是异步的(堆栈为空时调用)或同步的(调用后立即调用),这取决于状态更改的触发方式

现在这两件事很难消化

  • 在博客中,
    setState
    函数是在函数
    updateState
    中调用的,但是触发
    updateState
    函数的不是被调用函数所知道的
  • 为什么他们要使
    setState
    异步,因为JS是单线程语言,而这个setState不是WebAPI或服务器调用,所以只能在JS的线程上完成。他们这样做是为了重新渲染不会停止所有事件侦听器和其他东西,还是存在其他一些设计问题
  • 1)
    setState
    操作是异步的,并且为提高性能而成批执行。这在
    setState
    的文档中有说明

    setState()不会立即改变this.state,但会创建挂起的状态转换。调用此方法后访问this.state可能会返回现有值。 无法保证对setState调用的同步操作,并且可能会对调用进行批处理以提高性能


    2) 为什么他们要使setState异步,因为JS是单线程语言,而这个
    setState
    不是WebAPI或服务器调用?

    这是因为
    setState
    改变状态并导致重新招标。这可能是一个昂贵的操作,使其同步可能会使浏览器无响应。


    因此,setState调用是异步的,并且是批处理的,以获得更好的UI体验和性能。

    状态值更新后,您可以调用函数:

    this.setState({foo: 'bar'}, () => { 
        // Do something here. 
    });
    
    此外,如果您有许多状态需要一次更新,请将它们全部分组到同一个
    setState

    而不是:

    this.setState({foo: "one"}, () => {
        this.setState({bar: "two"});
    });
    
    只要这样做:

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

    或者传递callback
    this.setState({….},callback)


    我知道这个问题很老了,但很长一段时间以来,它给很多reactjs用户造成了很多困惑,包括我在内。 最近,react团队的丹·阿布拉莫夫(Dan Abramov)就
    setState
    的本质为何是异步的,写了一个很好的解释:

    setState
    是异步的,Dan Abramov的链接解释中有一些非常好的理由。这并不意味着它将始终是异步的,它主要意味着你不能依赖于它是同步的。ReactJS在您更改状态的场景中考虑了许多变量,以决定何时实际更新
    状态以及重新提交组件。

    一个简单的例子可以说明这一点,如果您调用
    setState
    作为对用户操作的反应,那么
    状态可能会立即更新(尽管您不能指望它),因此用户不会感觉到任何延迟,但是,如果您调用
    setState
    ,以响应ajax调用响应或用户未触发的其他事件,那么状态可能会稍微延迟更新,因为用户不会真正感受到这种延迟,它将通过同时等待批处理多个状态更新并减少DOM重新提交次数来提高性能。

    想象一下在某些组件中增加一个计数器:

      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>
            ...
          )
        }
      }
    
    要停止此行为,将传递回调,而不是将对象作为参数传递给setState方法

        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');
        }
    
    最后一个方法完成执行后,当react返回处理setState队列时,它只调用队列中每个setState的回调函数,传递上一个组件状态


    通过这种方式react可以确保队列中的最后一个回调能够更新其以前的所有对应回调都已处理过的状态。

    您可以使用以下wrap进行同步调用
    this.setState((状态=>{
    返回{
    某物
    }
    })
    是,setState()是异步的

    从链接:

    • React不保证立即应用状态更改
    • setState()并不总是立即更新组件
    • 将setState()视为更新组件的请求,而不是即时命令
    因为他们认为
    从链接:

    …我们同意,在许多情况下,同步重新呈现setState()将是低效的

    Asynchronous setState()让那些刚开始甚至不幸经历过的人的生活变得非常困难:
    -意外渲染问题:延迟渲染或不渲染(基于程序逻辑)
    -传递参数是件大事
    除其他问题外

    下面的例子有助于:

    // 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) {
        // ..
    }
    

    希望对您有所帮助。

    setState是异步的。您可以在Reactjs的文档中看到

    在开始重新渲染之前,故意“等待”所有组件在其事件处理程序中调用setState()。这通过避免不必要的重新渲染来提高性能

    但是,您可能仍然想知道为什么React不立即更新this.state而不重新渲染

    原因是这会破坏道具和状态之间的一致性,导致很难调试的问题

    如果取决于状态值的更改,您仍然可以执行以下功能:

    备选案文1: 在setState中使用回调函数

    this.setState({
       value: newValue
    },()=>{
       // It is an callback function.
       // Here you can access the update value
       console.log(this.state.value)
    })
    
    备选案文2:使用 只要特定类的状态发生更改,就会调用此函数

    componentDidUpdate(prevProps, prevState){
        //Here you can check if value of your desired variable is same or not.
        if(this.state.value !== prevState.value){
            // this part will execute if your desired variable updates
        }
    }
    

    看,我今天写了一篇文章,帮助描述了
    setState
    :否
    this.setState({
       value: newValue
    },()=>{
       // It is an callback function.
       // Here you can access the update value
       console.log(this.state.value)
    })
    
    componentDidUpdate(prevProps, prevState){
        //Here you can check if value of your desired variable is same or not.
        if(this.state.value !== prevState.value){
            // this part will execute if your desired variable updates
        }
    }