My approach is using ref
callback, which is kind of an onRenderComplete
of an element. In that callback I can focus (conditionally, if needed) and gain a reference for future focusing.
If the input is rendered conditionally after an action runs, that ref callback should fire a focus, because the ref doesn't exist yet immediately after calling the action, but only after render is done. Dealing with componentDidUpdate
for things like focus
just seems like a mess.
// Composer.jsx -- contains an input that will need to be focused somewhere else
class Composer extends Component {
render() {
return <input type="text" ref="input" />
}
// exposed as a public method
focus() {
this.refs.input.focus()
}
}
// App.jsx
@connect(
state => ({ isComposing: state.isComposing }),
...
)
class App extends Component {
render() {
const { isComposing } = this.props // or props, doesn't matter
return (
<div>
<button onClick={::this._onCompose}>Compose</button>
{isComposing ? <Composer ref={c => {
this._composer = c
this._composer && this._composer.focus() // issue initial focus
}} /> : null}
</div>
)
}
_onCompose() {
this.props.startComposing() // fire an action that changes state.isComposing
// the first time the action dispatches, this._composer is still null, so the ref takes care of the focus. After the render, the ref remains so it can be accessed:
this._composer && this._composer.focus() // focus if ref already exists
}
}
Why not autoFocus
or isFocued
prop?
As HTMLInputElement
has value
as a prop, but focus()
as a method -- and not isFocused
prop -- I would keep using methods to handle that. isFocused
can get a value but if the user blurs from the input, what happens to that value? It'll be out of sync. Also, as mentioned in the comments, autoFocus
can conflict with multiple components
So how to decide between props and methods?
For most cases props will be the answer. Methods can be used only in a 'fire and forget' things, such as scrollToBottom
in a chat when a new message comes in, scrollIntoView
and such. These are one time behaviors that the store doesn't care about and the user can change with an interaction, so a boolean prop won't fit. For all other things, I'd go with props.
Here's a jsbin:
http://jsbin.com/waholo/edit?html,js,output
autofocus
attribute. – Lavenialaver