
こんにちは! 今回は、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を使ったコンポーネント設計に挑戦してみてください!
関連する記事はこちら↓↓
