Deprecated

この API は、今後のメジャーバージョンの React で削除される予定です。代替案を見る

findDOMNode は、React class component インスタンスのブラウザ DOM ノードを見つけます。

const domNode = findDOMNode(componentInstance)

リファレンス

findDOMNode(componentInstance)

findDOMNode を呼び出して、指定された React class component インスタンスのブラウザ DOM ノードを見つけます。

import { findDOMNode } from 'react-dom';

const domNode = findDOMNode(componentInstance);

さらに例を見る

引数

  • componentInstance: Component サブクラスのインスタンス。例えば、クラスコンポーネントにある this になります。

返り値

findDOMNode は、指定された componentInstance に最も近いブラウザ DOM ノードを返します。コンポーネントが null をレンダーする場合や false をレンダーする場合、findDOMNodenull を返します。コンポーネントが文字列をレンダーする場合は findDOMNode は値を含むテキスト DOM ノードを返します。

注意点

  • コンポーネントは、配列や複数の子要素を持つ Fragment を返す場合もあります。その場合、findDOMNode は、最初の空ではない子に対応する DOM ノードを返します。

  • findDOMNode はマウントされたコンポーネント(つまり、DOM に配置されたコンポーネント)でのみ動作します。まだマウントされていないコンポーネント内から呼び出そうとすると(例えば、まだ作成されていないコンポーネントの render() 内から findDOMNode() を呼び出す場合)、例外がスローされます。

  • findDOMNode は、呼び出したときの結果のみを返します。子コンポーネントが後で異なるノードをレンダーする場合、この変更を通知されません。

  • findDOMNode はクラスコンポーネントインスタンスを受け取るため、関数コンポーネントで使用することはできません。


使用法

クラスコンポーネントのルート DOM ノードを見つける

class component インスタンス(通常は、this)を使用して findDOMNode を呼び出し、レンダーされた DOM ノードを見つけます。

class AutoselectingInput extends Component {
componentDidMount() {
const input = findDOMNode(this);
input.select()
}

render() {
return <input defaultValue="Hello" />
}
}

ここで、input 変数は <input> DOM 要素にセットされます。これにより、それを使用して何かを行うことができます。例えば、以下の “Show example” をクリックすると input はマウントされ、input.select() は input にあるすべてのテキストを選択します。

import { Component } from 'react';
import { findDOMNode } from 'react-dom';

class AutoselectingInput extends Component {
  componentDidMount() {
    const input = findDOMNode(this);
    input.select()
  }

  render() {
    return <input defaultValue="Hello" />
  }
}

export default AutoselectingInput;


代替手段

ref からコンポーネントの独自の DOM ノードを読み取る

findDOMNode を使用しているコードは壊れやすいです。なぜなら JSX ノードと対応する DOM ノードを操作するコード間の接続が明示的でないためです。例えば、この <input /><div> でラップしてみてください。

import { Component } from 'react';
import { findDOMNode } from 'react-dom';

class AutoselectingInput extends Component {
  componentDidMount() {
    const input = findDOMNode(this);
    input.select()
  }
  render() {
    return <input defaultValue="Hello" />
  }
}

export default AutoselectingInput;

このコードは壊れるでしょう。なぜなら、コードは <input> DOM ノードを期待していましたが、findDOMNode(this)<div> DOM ノードを見つけたためです。このような問題を避けるために、特定の DOM ノードを管理するために createRef を使用してください。

この例では、findDOMNode は使用されていません。代わりに、inputRef = createRef(null) がクラスのインスタンスフィールドとして定義されています。DOM ノードを読み取るには、this.inputRef.current を使用できます。それを JSX にアタッチするには、<input ref={this.inputRef} /> をレンダーします。これにより、DOM ノードを使用するコードがその JSX に接続されます。

import { createRef, Component } from 'react';

class AutoselectingInput extends Component {
  inputRef = createRef(null);

  componentDidMount() {
    const input = this.inputRef.current;
    input.select()
  }

  render() {
    return (
      <input ref={this.inputRef} defaultValue="Hello" />
    );
  }
}

export default AutoselectingInput;

クラスコンポーネントがないモダンな React では、代わりに useRef を呼び出した同等のコードになります。

import { useRef, useEffect } from 'react';

export default function AutoselectingInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    const input = inputRef.current;
    input.select();
  }, []);

  return <input ref={inputRef} defaultValue="Hello" />
}

refs を使用して DOM を操作する方法についての詳細はこちら


forwarded ref から子コンポーネントの DOM ノードを読み取る

この例では、findDOMNode(this) は別のコンポーネントに属する DOM ノードを見つけます。AutoselectingInput は、ブラウザの <input> をレンダーする独自のコンポーネントである MyInput をレンダーします。

import { Component } from 'react';
import { findDOMNode } from 'react-dom';
import MyInput from './MyInput.js';

class AutoselectingInput extends Component {
  componentDidMount() {
    const input = findDOMNode(this);
    input.select()
  }
  render() {
    return <MyInput />;
  }
}

export default AutoselectingInput;

AutoselectingInput 内にある findDOMNode(this) を呼び出すと、DOM の <input> を取得します。しかし、この <input> の JSX は MyInput コンポーネントの中に隠れています。この上の例では便利に思えますが、壊れやすいコードになりやすいです。MyInput を編集して、それをラップする <div> を追加するとどうなるでしょうか。AutoselectingInput のコードが壊れます(<input> が見つかることを期待している)。

この例の findDOMNode を置き換えるには、2 つのコンポーネントが連携する必要があります:

  • 1.AutoSelectingInputref を宣言し、前述の例のように <MyInput> に渡す必要があります。
  • 2.MyInputforwardRef で宣言され、その ref を取り、それを <input> ノードに転送する必要があります。

このバージョンはそれを行うので、もはや findDOMNode は必要ありません。

import { createRef, Component } from 'react';
import MyInput from './MyInput.js';

class AutoselectingInput extends Component {
  inputRef = createRef(null);

  componentDidMount() {
    const input = this.inputRef.current;
    input.select()
  }

  render() {
    return (
      <MyInput ref={this.inputRef} />
    );
  }
}

export default AutoselectingInput;

クラスの代わりに関数コンポーネントを使用するとコードはどうなるのでしょうか:

import { useRef, useEffect } from 'react';
import MyInput from './MyInput.js';

export default function AutoselectingInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    const input = inputRef.current;
    input.select();
  }, []);

  return <MyInput ref={inputRef} defaultValue="Hello" />
}


<div> 要素のラッパーを追加する

コンポーネントは時々、子要素の位置やサイズを知る必要があります。そのため、findDOMNode(this) で子要素を見つけ、getBoundingClientRect のような DOM メソッドを使って計測したくなります。

現在、このユースケースに直接対応できるものは存在しないため、findDOMNode が非推奨となっていますが、まだ完全に React から削除されていません。その間、コンテンツの周りにラッパーとして <div> ノードをレンダーし、そのノードへの ref を取得するという回避策を試せます。ただし、余分なラッパーはスタイリングを壊す可能性があります。

<div ref={someRef}>
{children}
</div>

これは、任意の子要素にフォーカスや、スクロールにも適用されます。