在输入 onChange 上强调和延迟 React 的 setState

Accent and deferred React's setState on input onChange

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

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 上,重音符号和字母不会出现。

你们有什么线索吗?

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

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

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

发生了什么:

假设您按下字母 A

  1. 当你触发字段中的onChange时,React处理所有的状态变化。

  2. 在状态突变过程之后,React 做 DOM diff 来更新组件,在这个阶段这个字段的状态值是一个空值,所以 React 做一个 node.value = "".

  3. 在下一个价格变动时,我们的延迟 setState 被触发应用字母 Anode.value = "A"

此行为会破坏 MacOS 上的浏览​​器,它们会将 "intermediate state" 上的重音替换为键入的重音,从而阻止用户键入重音字符。

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