【问题标题】:React.js input cursor reset with async onChange handler使用异步 onChange 处理程序重置 React.js 输入光标
【发布时间】:2017-04-09 11:55:42
【问题描述】:

如果我有以下反应组件:

class Cmpt extends Component {
   setValue( e ) {
     this.setState({ value : e.target.value });
   }
   render() {
     return <input value={this.state.val} onChange={this.setValue.bind(this)}/>
   }
}

现在这可以按预期工作,编辑文本不会将光标重置到输入的末尾。如果我修改它以使 setState 异步发生,则会发生光标重置:

class Cmpt extends Component {
   setValue( e ) {
     setTimeout( () =>
       this.setState({ value : e.target.value }) );
   }
   render() {
     return <input value={this.state.val} onChange={this.setValue.bind(this)}/>
   }
}

显然解决方法是不同步调用setState - 但我不明白为什么异步版本不能正常工作。在我的脑海中,事件链如下:

  1. 用户将字符添加到输入字段,将其从 ACD 更改为 ABCD
  2. 输入 DOM 节点的值更改为 ABCD 以反映这一点
  3. 一段时间过去了
  4. setState 被调用 - 将反应组件的状态从 ACD 更改为 ABCD
  5. 触发了render 调用 - React 差异算法将 DOM 节点值 (ABCD) 与 this.state.value (ABCD) 的值进行比较。它看到两者是相同的,因此不会触发重绘并保留光标

显然我的心智模型是错误的,因为正在触发重绘 - 导致光标重置。

谁能解释一下原因?

谢谢!

【问题讨论】:

标签: reactjs asynchronous input cursor reset


【解决方案1】:

状态更改将始终触发新的render 调用。之后,React 自己决定重新渲染什么。但它总是会通过改变状态来触发。即使你这样做了

this.setState({})

它将调用render 方法。

【讨论】:

  • 当然,但我的问题是为什么当 setState 被称为异步与同步时,React 选择重新渲染文本输入(导致光标重置)
【解决方案2】:

抱歉各位,发现一个重复的问题回答了我的问题:

In ReactJS, why does `setState` behave differently when called synchronously?

不幸的是,我不知道如何将我自己的问题标记为重复 :(

我对事件顺序的心理模型是错误的。显然 react 会在每个事件处理程序结束时触发同步重新渲染,因此渲染被调用 after DOM 更改,但 before 反应状态已更改 - 导致重绘和光标重置

谢谢大家

T

【讨论】:

    猜你喜欢
    • 2014-01-28
    • 2020-04-09
    • 1970-01-01
    • 2022-11-10
    • 2021-06-22
    • 2013-10-15
    • 2013-01-06
    • 1970-01-01
    • 2011-06-23
    相关资源
    最近更新 更多