当前位置: 首页 > 面试题库 >

在ReactJS中,为什么setState在同步调用时表现不同?

查学文
2023-03-14
问题内容

我试图了解某些“魔术”行为的根本原因,但我无法完全解释,而从阅读ReactJS源代码中看不出来。

setState响应onChange输入中的事件而同步调用该方法时,所有操作均按预期进行。输入的“新”值已经存在,因此DOM实际上并未更新。这是非常理想的,因为这意味着光标不会跳到输入框的末尾。

但是,当运行具有完全相同结构但setState 异步
调用的组件时,输入的“新”值似乎不存在,从而导致ReactJS实际触摸DOM,这将导致光标跳至DOM的末尾。输入。

显然,value在异步情况下有某种干预将输入“重置”回其先前状态,而在同步情况下则没有。这个机械师是什么?

同步示例

var synchronouslyUpdatingComponent =
    React.createFactory(React.createClass({
      getInitialState: function () {
        return {value: "Hello"};
      },

      changeHandler: function (e) {
        this.setState({value: e.target.value});
      },

      render: function () {
        var valueToSet = this.state.value;

        console.log("Rendering...");
        console.log("Setting value:" + valueToSet);
        if(this.isMounted()) {
            console.log("Current value:" + this.getDOMNode().value);
        }

        return React.DOM.input({value: valueToSet,
                                onChange: this.changeHandler});
    }
}));

请注意,代码将登录该render方法,并打印出value实际DOM节点的当前值。

在“ Hello”的两个L之间键入“ X”时,我们看到以下控制台输出,并且光标停留在预期的位置:

Rendering...
Setting value:HelXlo
Current value:HelXlo

异步示例

var asynchronouslyUpdatingComponent =
  React.createFactory(React.createClass({
    getInitialState: function () {
      return {value: "Hello"};
    },

    changeHandler: function (e) {
      var component = this;
      var value = e.target.value;
      window.setTimeout(function() {
        component.setState({value: value});
      });
    },

    render: function () {
      var valueToSet = this.state.value;

      console.log("Rendering...");
      console.log("Setting value:" + valueToSet);
      if(this.isMounted()) {
          console.log("Current value:" + this.getDOMNode().value);
      }

      return React.DOM.input({value: valueToSet,
                              onChange: this.changeHandler});
    }
}));

与上面的内容完全相同,但对的调用setState位于setTimeout回调中。

在这种情况下,在两个L之间键入X将产生以下控制台输出,并且光标跳至输入的末尾:

Rendering...
Setting value:HelXlo
Current value:Hello

为什么是这样?

我了解React的受控组件的概念,因此用户对的更改value被忽略是有意义的。但看起来value实际上已更改,然后显式重置。

显然,调用setState同步确保其生效 之前 复位,同时呼吁setState在其他任何时间发生 复位,迫使重新绘制。

这实际上是怎么回事吗?

JS Bin示例

http://jsbin.com/sogunutoyi/1/


问题答案:

这是正在发生的事情。

同步

  • 你按X
  • input.value是’HelXlo’
  • 你打电话 setState({value: 'HelXlo'})
  • 虚拟dom表示输入值应为“ HelXlo”
  • input.value是’HelXlo’
    • 不采取行动

异步

  • 你按X
  • input.value是’HelXlo’
  • 你什么都不做
  • 虚拟DOM表示输入值应为“ Hello”
    • react使input.value为“ Hello”。

稍后的…

  • setState({value: 'HelXlo'})
  • 虚拟DOM表示输入值应为“ HelXlo”
    • 反应使输入值``HelXlo’‘
    • 浏览器将光标跳到末尾(这是设置.value的副作用)

魔法?

是的,这里有些魔术。在事件处理程序之后,React调用将同步呈现。这是避免闪烁所必需的。



 类似资料:
  • 我刚刚发现,在react函数都是异步的,或者在调用它的函数完成后调用。 现在这两样东西很难消化 在博客中,函数是在函数内部调用的,但是触发函数的原因并不是被调用函数所知道的。 他们为什么要让异步,因为JS是单线程语言,而且这个setState不是WebAPI或服务器调用,所以只能在JS的线程上完成。他们这样做是为了使重新呈现不会停止所有事件侦听器和其他东西,还是有其他设计问题。

  • 问题内容: 我在这里阅读的内容是jquery中的同步ajax调用不会超时。 这是技术上的限制吗,还是仅仅是作者不想支持的东西?当ajax调用是同步的时,在表下实际发生了什么? 问题答案: 浏览器通过XMLHttpRequest API 处理同步/异步请求,但没有内置的超时功能。JQuery在浏览器XHR API之上的JavaScript中实现自己的超时。 由于同步调用会阻止所有正在运行的脚本,因此

  • React是否在每次调用时重新呈现所有组件和子组件? 如果是,为什么?我认为这个想法是,当状态改变时,只会根据需要提供少量的反应。 我希望只有在数据发生更改时才会出现呈现。 下面是示例的代码,作为JS Fiddle和嵌入的代码片段:

  • React引入了新的静态方法,它在每个呈现方法之前都会被调用,但为什么呢?在prop change之后调用它对我来说是有意义的,但是在之后调用它就没有意义了,也许我错过了什么。 我根据公司的要求创建了一个组件,在组件中日期是从道具控制的。我在组件中有以下状态。 是的,我在中创建了一个额外的变量来跟踪是否由于而被调用,但我认为这不是正确的方法。 或者是我做错了什么或者遗漏了什么,或者不应该在之后调用

  • 我试着读过类似的问题,但没有成功。

  • 问题内容: 这是一个Java代码段: 而且它根据不同的JDK表现不同 在Oracle JDK 1.7中的输出是: 在OpenJDK 1.6中的输出也是: 但是在Oracle JDK 1.6中,输出为: 如此方法的JavaDoc所指示 输出: 应该可以预期,但是三个JDK都不会产生这种情况。以及Oracle JDK1.6为什么提供: 结果是? 我认为在OracleJDK 1.7和openJDK 1.