Reputation: 550
Dumb React question: how to set focus on input after it displayed and why my code doesn't work? (Without display toggle it works.)
edit: What I expect: after click on a button, the input field appears (by removing .dnone class) and get a focus on it. (But it doesn't.)
My code:
import "./styles.css"; // with .dnone class with display:none
import React from 'react';
export default class App extends React.Component {
constructor(props) {
super(props);
this.input = React.createRef();
this.state = {
active: false
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
this.input.current.focus();
}
render () {
return (
<div className="App">
<input type="text" ref={this.input} className={(this.state.active ? "" : "dnone")} />
<button type="button" onClick={(e) => this.click(e)}>click</button>
</div>
);
}
}
live demo: https://codesandbox.io/s/immutable-sea-9884z?file=/src/App.js:0-607
Thank you!
Upvotes: 3
Views: 3638
Reputation: 203062
The issue is that React state updates are asynchronously processed, so in the click handler when you enqueue a state update you are immediately attempting to focus on the input, but since the active
state hasn't updated yet you can't, the dnone
classname hasn't been removed and input made visible yet.
Move the focus logic into the componentDidUpdate
lifecycle method to "respond" to the active
state updating.
componentDidUpdate(prevProps, prevState) {
if (prevState.active !== this.state.active && this.state.active) {
this.input.current.focus();
}
}
click = (e) => {
e.preventDefault();
this.setState({
active: true
});
}
Upvotes: 2