簡潔な答え:
レフリーが前に設定されていることを保証反応componentDidMount
やcomponentDidUpdate
フックを。ただし、実際にレンダリングされた子供のみが対象です。
componentDidMount() {
}
componentDidUpdate() {
}
render() {
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が他の条件下で、参照を添付する必要のある何かを返すことを知る方法はありません。ありませんへの参照を設定するものは何も:<div>
ので、要素が作成されていないrender()
メソッドは、それがレンダリングされるべきではないと述べました。
したがって、この例では、のみcomponentDidMount
が起動します。ただし、にthis.state.loading
変更するとfalse
、this._setRef
最初に添付が表示され、次に起動しますcomponentDidUpdate
。
他のコンポーネントに注意してください
refを持つ子を他のコンポーネントに渡すと、レンダリングを妨げる(そして問題を引き起こす)何かをしている可能性があることに注意してください。
たとえば、これは次のとおりです。
<MyPanel>
<div ref={this.setRef} />
</MyPanel>
出力にMyPanel
含まprops.children
れていない場合は機能しません:
function MyPanel(props) {
return <h1>Oops, no refs for you today!</h1>;
}
繰り返しますが、これはバグではありません。DOM要素が作成されていないため、Reactが参照を設定することはありません。
ネストされた参照に渡された場合、参照はライフサイクルの前に設定されません 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に問題を提出してください。調査します。
this
、クラス外の字句スコープからの値をキャプチャします。クラスメソッドの矢印関数構文を削除して、それが役立つかどうかを確認してください。