リファレンス
PreactによってレンダリングされたDOM要素またはコンポーネントへの直接参照が必要となるシナリオは常に存在します。リファレンスを使用すると、まさにそれができます。
典型的なユースケースは、DOMノードの実際のサイズを測定することです。ref
を介してコンポーネントインスタンスへの参照を取得することは可能ですが、一般的にはお勧めしません。 親と子の間に強い結合が生じ、コンポーネントモデルのコンポーザビリティが損なわれます。 ほとんどの場合、クラスコンポーネントのメソッドを直接呼び出そうとするのではなく、コールバックをプロパティとして渡す方が自然です。
createRef
createRef
関数は、current
というプロパティだけを持つプレーンオブジェクトを返します。render
メソッドが呼び出されるたびに、Preact は DOM ノードまたはコンポーネントを current
に代入します。
class Foo extends Component {
ref = createRef();
componentDidMount() {
console.log(this.ref.current);
// Logs: [HTMLDivElement]
}
render() {
return <div ref={this.ref}>foo</div>
}
}
REPLで実行コールバック Ref
要素への参照を取得する別の方法は、関数コールバックを渡すことです。少しタイプ量が多くなりますが、createRef
と同様に機能します。
class Foo extends Component {
ref = null;
setRef = (dom) => this.ref = dom;
componentDidMount() {
console.log(this.ref);
// Logs: [HTMLDivElement]
}
render() {
return <div ref={this.setRef}>foo</div>
}
}
REPLで実行ref コールバックがインライン関数として定義されている場合、2 回呼び出されます。 1 回目は
null
で、2 回目は実際の参照です。これはよくあるエラーであり、createRef
API はユーザーにref.current
が定義されているかどうかを確認させることで、これを少し容易にします。
すべてをまとめる
DOM ノードへの参照を取得して、その幅と高さを測定する必要があるシナリオがあるとします。 プレースホルダー値を実際に測定された値に置き換える必要がある単純なコンポーネントがあるとします。
class Foo extends Component {
// We want to use the real width from the DOM node here
state = {
width: 0,
height: 0,
};
render(_, { width, height }) {
return <div>Width: {width}, Height: {height}</div>;
}
}
測定は、render
メソッドが呼び出され、コンポーネントが DOM にマウントされた後にのみ意味を持ちます。 それ以前は DOM ノードは存在せず、測定しようとしてもあまり意味がありません。
class Foo extends Component {
state = {
width: 0,
height: 0,
};
ref = createRef();
componentDidMount() {
// For safety: Check if a ref was supplied
if (this.ref.current) {
const dimensions = this.ref.current.getBoundingClientRect();
this.setState({
width: dimensions.width,
height: dimensions.height,
});
}
}
render(_, { width, height }) {
return (
<div ref={this.ref}>
Width: {width}, Height: {height}
</div>
);
}
}
REPLで実行これで完了です! コンポーネントは、マウントされると常に幅と高さを表示するようになります。