I'm creating a little utility where I need call a setState
deferred to next tick fired by an input's onChange
handler. Below a simple snippet showing the basic concept.
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")
);
If you run this snippet in a browser on Mac OS and try to type some letter with an accent you get an awkward behavior different on each browser. On Chrome the accent only works for the first time, after the accent isn't applied anymore (take a look on the gif below). On Firefox, the accent and letter don't appear.
Do you guys have any clue about this?
p.s.: I tested this behavior on React 0.13, 0.14 and 15.0.2.
Basically you shouldn't defer the setState
. React won't work properly in this situation.
Look: https://github.com/facebook/react/issues/6563
What is happening:
Let's suppose that you press the letter A
.
When you trigger the onChange
in the field, React processes all the state mutations.
After the state mutation process, React does the DOM diff to update the component and at this stage the state value for this field is an empty value, so React does a node.value = ""
.
On the next tick our deferred setState
is triggered applying the letter A
with the node.value = "A"
.
This behavior breaks the browsers on MacOS where they replace the accent on the "intermediate state" to a typed accent preventing user to type the accentuated character.
So, sadly there's no solution.