我的方法是使用ref 回调,这是一种元素的onRenderComplete。在那个回调中,我可以集中注意力(如果需要,有条件地)并获得未来关注的参考。
如果输入在动作运行后有条件地呈现,则该 ref 回调应触发焦点,因为在调用该动作后该 ref 还不存在,但仅在渲染完成后才存在。处理componentDidUpdate 之类的focus 似乎是一团糟。
// 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
}
}
为什么不用autoFocus 或isFocued 道具?
由于HTMLInputElement 有value 作为道具,但focus() 作为方法——而不是isFocused 道具——我会继续使用方法来处理它。 isFocused 可以得到一个值,但是如果用户从输入中模糊,该值会发生什么?会不同步。此外,正如 cmets 中所述,autoFocus 可能与多个组件发生冲突
那么如何在 props 和 methods 之间做出选择呢?
在大多数情况下,道具就是答案。方法只能用于“一劳永逸”的事情,例如scrollToBottom 在有新消息时的聊天中,scrollIntoView 等。这些是商店不关心的一次性行为,用户可以通过交互进行更改,因此布尔属性不适合。对于所有其他事情,我会选择道具。
这是一个 jsbin:
http://jsbin.com/waholo/edit?html,js,output