ヘルプ
ご支援ください

リファレンス

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で実行

これで完了です! コンポーネントは、マウントされると常に幅と高さを表示するようになります。