こんにちは! 今回は、Reactでよく使われるforwardRef
という機能について、わかりやすく解説していきます。この機能を使うと、コンポーネント間でのデータのやりとりがもっと柔軟になります。
はじめに
Reactでは、通常、親コンポーネントから子コンポーネントにデータを渡すという形でデータフローが行われます。たとえば、以下のコードを見てください。
function ChildComponent({ message }) {
return <p>{message}</p>;
}
function ParentComponent() {
return <ChildComponent message="Hello from Parent!" />;
}
このコードでは、ParentComponent
からChildComponent
に対して、message
というプロパティ(props)が渡されています。Reactの基本的な流れとして、データは親から子へと流れます。
しかし、DOM操作やカスタムロジックが必要な場合には、子コンポーネントが親コンポーネントからref
を受け取り、親が子のDOM要素を直接操作するような仕組みが必要になることがあります。これを可能にするのがforwardRef
です。
forwardRefとは?
forwardRef
は、親コンポーネントから渡されたref
を子コンポーネント内で受け取り、そのままDOM要素や別の子コンポーネントに渡すためのReactの関数です。
これを使うことで、親コンポーネントが子コンポーネント内部のDOM要素に直接アクセスできるようになります。
たとえば、次のように使います。
import React, { forwardRef } from 'react';
const InputComponent = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
function ParentComponent() {
const inputRef = React.createRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<InputComponent ref={inputRef} placeholder="Type something..." />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
コードのポイント
InputComponent
は、forwardRef
を使って作られています。これにより、親コンポーネントから渡されたref
を受け取り、それを<input>
タグのref
に渡しています。- 親コンポーネントの中で
React.createRef()
を使い、ref
を作成しています。 focusInput
メソッドでref.current.focus()
を呼び出すことで、親コンポーネントから子の<input>
にフォーカスを当てることができます。
このように、forwardRef
を使うことで、親コンポーネントが直接子のDOM要素を操作できるようになります。
通常のrefと何が違うの?
通常、Reactでref
を使う場合、親が直接DOM要素にref
を渡すことができます。しかし、以下のようなケースではforwardRef
が必要になります。
例: 通常のrefでは対応できない場合
function InputComponent(props) {
return <input {...props} />;
}
function ParentComponent() {
const inputRef = React.createRef();
return (
<div>
<InputComponent ref={inputRef} placeholder="Cannot use ref here!" />
</div>
);
}
このコードを実行するとエラーになります。なぜなら、InputComponent
は通常の関数コンポーネントであり、ref
をそのままDOM要素に渡す機能がないからです。
解決策: forwardRefを使う
const InputComponent = React.forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
function ParentComponent() {
const inputRef = React.createRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<InputComponent ref={inputRef} placeholder="Now it works!" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
このように、forwardRef
を使うことで、親から子へref
を渡すことが可能になります。
応用: コンポーネントとDOMの橋渡し
forwardRef
は単にDOM要素にアクセスするだけでなく、コンポーネント間のロジックを柔軟にするためにも使えます。たとえば、次のようにカスタムフックや複雑な構造を持つコンポーネントと組み合わせることができます。
応用例: 高度なコンポーネント
const FancyInput = forwardRef((props, ref) => {
return (
<div style={{ border: '1px solid black', padding: '10px' }}>
<input ref={ref} {...props} />
</div>
);
});
function App() {
const inputRef = React.createRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<h1>Fancy Input Example</h1>
<FancyInput ref={inputRef} placeholder="Click the button to focus" />
<button onClick={focusInput}>Focus Fancy Input</button>
</div>
);
}
この例では、FancyInput
が内部に<input>
を持ちながら、そのref
を親から操作可能にしています。これにより、見た目や構造が複雑なコンポーネントでも、簡単に親コンポーネントから操作できます。
公式ドキュメント
React公式ドキュメントでは、forwardRef
の詳細な仕様について解説されています。ぜひ参考にしてください!
まとめ
forwardRef
を使うと、ReactアプリケーションでのDOM操作やコンポーネント間の連携がとても柔軟になります。
- 通常のデータフローではできない子コンポーネントのDOM要素へのアクセスが可能。
- 複雑な構造やカスタムロジックを持つコンポーネントでも、親から簡単に制御可能。
これを機に、ぜひforwardRef
を使ったコンポーネント設計に挑戦してみてください!
関連する記事はこちら↓↓