If I have the following react component:
class Cmpt extends Component {
setValue( e ) {
this.setState({ value : e.target.value });
}
render() {
return <input value={this.state.val} onChange={this.setValue.bind(this)}/>
}
}
Now this works as expected, editing the text doesn't reset the cursor to the end of the input. If I modify it such that the setState happens in async, the cursor reset occurs:
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)}/>
}
}
Obviously the fix is to not call setState
synchronously - but I don't understand why the async version doesn't work properly. In my head, the chain of events is as follows:
- User adds a character to an input field, changing it from ACD to ABCD
- The value of the input DOM node is changed to ABCD to reflect this
- Some time passes
setState
is called - changing the state of the react component from ACD to ABCD- a
render
call is triggered - the React diffing algorithm compares the DOM nodes value (ABCD) to the value ofthis.state.value
(ABCD). It sees that both are the same and therefore doesn't trigger a redraw and the cursor is preserved
Clearly my mental model is wrong because a redraw is being triggered - causing the cursor reset.
Please can anyone explain why?
Thanks!