输入onChange

时间:2016-05-17 03:29:59

标签: javascript reactjs deferred

我正在创建一个小实用程序,我需要调用setState延迟到输入的onChange处理程序触发的下一个tick。下面是一个显示基本概念的简单片段。

https://jsfiddle.net/samuelsimoes/q3p44sz1/

class MyComponent extends React.Component {
  constructor () {
    super(...arguments);
    this.state = {};
  }

  onChange (value) {
    setTimeout(v => {
      this.setState({ name: v });
    }.bind(this, value), 0);
  }

  render () {
    return (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={evt => this.onChange(evt.target.value)} />
      </div>
    );
  }
};

ReactDOM.render(
  <MyComponent/>,
  document.getElementById("app-container")
);

如果您在Mac OS上的浏览器中运行此代码段并尝试键入带有重音符号的某个字母,则会在每个浏览器上产生不同的尴尬行为。在Chrome上,重音仅适用于第一次,不再应用重音(请查看下面的gif)。在Firefox上,重音和字母不会出现。

Bug on Chrome

你们对此有什么线索吗?

p.s。:我在React 0.13,0.14和15.0.2上测试了这种行为。

1 个答案:

答案 0 :(得分:2)

基本上你不应该推迟setState。在这种情况下,React不能正常工作。

看:https://github.com/facebook/react/issues/6563

发生了什么:

我们假设你按下A字母。

  1. 当您在字段中触发onChange时,React会处理所有状态突变。

  2. 在状态变异过程之后,React执行DOM diff以更新组件,在此阶段,此字段的状态值为空值,因此React执行node.value = ""

  3. 在下一个刻度线上,我们将延迟setStateA一起应用字母node.value = "A"

  4. 这种行为打破了MacOS上的浏览器,它们取代了#34;中间状态&#34;到键入的重音,防止用户键入突出的字符。

    所以,遗憾的是没有解决方案。