简短答案:
React保证引用被设置在componentDidMount
或componentDidUpdate
钩子之前。但仅适用于 实际上被渲染
过的孩子 。
componentDidMount() { // can use any refs here}componentDidUpdate() { // can use any refs here}render() { // as long as those refs were rendered! return <div ref={} />;}请注意,这并不意味着“ React总是在运行这些挂钩之前设置 所有 引用”。
让我们看一些 没有 设置参考的示例。
引用未设置未渲染的元素
React只会为您实际 从render返回的 元素调用ref回调。
这意味着如果您的代码看起来像
render() { if (this.state.isLoading) { return <h1>Loading</h1>; } return <div ref={this._setRef} />;}并初步
this.state.isLoading是
true,你应该 不
希望
this._setRef之前调用
componentDidMount。
这应该是有道理的:如果您的第一个渲染器返回了
<h1>Loading</h1>,React无法知道在其他条件下它会返回需要附加引用的其他内容。也
没有将ref设置为的内容:
<div>元素未创建,因为
render()方法表示不应渲染该元素。
因此,在此示例中,只会
componentDidMount触发。但是,对
进行
this.state.loading更改时
false,您将
this._setRef首先看到附件,然后
componentDidUpdate将其触发。
提防其他组件
请注意, 如果您将带有ref的子级传递给其他组件 ,则它们可能会执行某些阻止渲染的操作(并导致问题)。
例如,这:
<MyPanel> <div ref={this.setRef} /></MyPanel>如果其输出中
MyPanel未包含以下内容
props.children,则将不起作用:
function MyPanel(props) { // ignore props.children return <h1>Oops, no refs for you today!</h1>;}再说一次,这不是一个错误: React没有任何设置引用的原因,因为DOM元素没有创建 。
如果将引用传递给嵌套,则它们不会在生命周期之前设置 ReactDOM.render()
与上一节类似,如果将带有ref的孩子传递到另一个组件,则此组件可能会执行某些阻止及时附加ref的操作。
例如,也许不是从中返回子项
render(),而是调用
ReactDOM.render()了生命周期挂钩。您可以在这里找到一个示例。在该示例中,我们呈现:
<MyModal> <div ref={this.setRef} /></MyModal>但是在 其 生命周期方法中
MyModal执行
ReactDOM.render()调用: __
componentDidUpdate
componentDidUpdate() { ReactDOM.render(this.props.children, this.targetEl);}render() { return null;}从React 16开始, 生命周期内的 此类 顶级渲染调用将被延迟,直到整个树的生命周期都已运行为止 。这可以解释为什么您没有及时看到引用。
解决此问题的方法是使用
门户网站而不是嵌套ReactDOM.render
调用:
render() { return ReactDOM.createPortal(this.props.children, this.targetEl);}这样
<div>,带有ref的我们实际上包含在渲染输出中。
因此,如果遇到此问题,则需要验证组件和ref之间没有任何东西可能会延迟渲染子级。
不要setState
用来存储裁判
确保您
setState不习惯将ref存储在ref回调中,因为它是异步的,并且在“完成”之前
componentDidMount将首先执行。
还是一个问题?
如果以上提示均无济于事,请在React中提出问题,我们将进行调查。



