When focused in the input box, hitting enter submits the form. On submit, an error causes an error to be inserted into the state which causes a rerender and creates a new element to show the error.
{error && <div>{error}</div>}
This rerenders the entire component which is unnecessary.
Surely (p)react should be able to detect that only the new error element be inserted and the rest of the DOM can remain untouched?
A consequence of this is that I lose focus of the input but also that a stripe iframe is remounted. How can I prevent this
export default class App extends Component {
state = { val: "Sample input", error: null };
onSubmit = e => {
e.preventDefault();
this.setState({ error: "Some error" });
};
render(props, { val, error }) {
return (
<div>
<h1>Example</h1>
<form onSubmit={this.onSubmit}>
{error && <div>{error}</div>}
<div class="list">
<input
value={val}
onChange={e => this.setState({ val: e.target.value })}
/>
<button type="submit">Submit</button>
</div>
</form>
</div>
);
}
}
The issue is how react reconciles children.
Solution 1 I can avoid rerendering the entire component and maintain focus by adding the key
attribute to the conditional component.
{error && <div key='formError'>{error}</div>}
Solution 2 Alternatively I could move the conditional error below the input
<div class="list">
<input
value={val}
onChange={e => this.setState({ val: e.target.value })}
/>
<button type="submit">Submit</button>
</div>
{error && <div>{error}</div>}
Solution 3 Or use a class to hide the error
<div className={error ? 'error' : 'hide'}>{error}</div>
Initially you have <div>
with input
inside. After submitting form component will need to display two <div>
: one for error and one for form. But what to update and what to create? Without key
and having two elements of exact constructor React decides to update existing with error message(and removing form away) and to create new one where form will be rendered.
And at this move it loses focus inside field. So it's not because of re-render in general but because of reconciliation specifically.
So yes, nice catch, key
solves that by suggesting React not to mess within div
s but create new for error message. If you had different elements(say, div
and... ul
) you will never experience that. But providing key
also legit way to handle that. Maybe slightly confusing from first glance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With