useImperativeHandle 完全入門【React】refで公開するAPIを制御する
ReactのuseImperativeHandleとは何か、親コンポーネントから子コンポーネントのメソッドを呼び出す方法を初心者向けに解説。forwardRefとの組み合わせ方や具体的な使用例も紹介します。
「子コンポーネントのフォームにフォーカスを当てたい」「子コンポーネントのアニメーションを親から制御したい」——そんなときに使うのが useImperativeHandle です。
通常のReactでは、データはpropsを通じて親から子へ流れます。しかし、DOMの操作やアニメーションなど命令的な操作が必要な場面では、親から子のメソッドを直接呼び出したいことがあります。useImperativeHandle はこのような場面で役立つフックです。
この記事でわかること:
useImperativeHandleが必要な場面forwardRefとの組み合わせ方- 親から子のメソッドを呼び出す実装パターン
- 使いすぎを避けるためのベストプラクティス
useImperativeHandle とは?
useImperativeHandle は、親コンポーネントに公開する ref の内容をカスタマイズするフックです。
通常 ref をコンポーネントに渡すと、親はそのコンポーネントの DOM ノード全体にアクセスできてしまいます。useImperativeHandle を使うと、公開するメソッドを必要なものだけに限定できます。
useImperativeHandle(ref, createHandle関数, 依存配列);| パラメータ | 説明 |
|---|---|
ref | 親から渡された ref オブジェクト |
createHandle | 公開するメソッドを含むオブジェクトを返す関数 |
dependencies | (省略可能)再生成のトリガーとなる値の配列 |
戻り値は undefined です。
基本的な使い方
React 19 以降では ref が通常の props として渡せるようになりました。
import { useRef, useImperativeHandle } from "react";
// 子コンポーネント
function FancyInput({ ref }) {
const inputRef = useRef(null);
// 親に公開するメソッドを定義
useImperativeHandle(ref, () => ({
focus() {
inputRef.current.focus();
},
clear() {
inputRef.current.value = "";
},
}));
return <input ref={inputRef} type="text" />;
}
// 親コンポーネント
function Form() {
const fancyInputRef = useRef(null);
const handleClick = () => {
fancyInputRef.current.focus(); // 子のfocusメソッドを呼び出す
};
return (
<>
<FancyInput ref={fancyInputRef} />
<button onClick={handleClick}>フォーカス</button>
</>
);
}React 18 以前の書き方(forwardRef)
React 18 以前では forwardRef でコンポーネントをラップする必要があります。
import { useRef, useImperativeHandle, forwardRef } from "react";
// forwardRef でラップする
const FancyInput = forwardRef(function FancyInput(props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView({ behavior: "smooth" });
},
}));
return <input ref={inputRef} type="text" />;
});実用的な使用例:動画プレイヤーの制御
import { useRef, useImperativeHandle } from "react";
function VideoPlayer({ src, ref }) {
const videoRef = useRef(null);
// play/pause/seek だけを親に公開する
useImperativeHandle(ref, () => ({
play() {
videoRef.current.play();
},
pause() {
videoRef.current.pause();
},
seekTo(seconds) {
videoRef.current.currentTime = seconds;
},
}));
return <video ref={videoRef} src={src} />;
}
function App() {
const playerRef = useRef(null);
return (
<>
<VideoPlayer ref={playerRef} src="/movie.mp4" />
<button onClick={() => playerRef.current.play()}>再生</button>
<button onClick={() => playerRef.current.pause()}>一時停止</button>
<button onClick={() => playerRef.current.seekTo(30)}>30秒へ</button>
</>
);
}いつ使うべきか?避けるべきか?
useImperativeHandle は命令的な操作にのみ使うのが原則です。
適切な使用例:
- フォームへのフォーカス
- スクロール位置の制御
- アニメーションのトリガー
- テキストの選択
避けるべきケース:
// ❌ NG:propsで表現できるものにrefを使わない
// Modal に open/close メソッドを持たせるより...
ref.current.open();
// ✅ OK:isOpen props で制御する
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} />なるべく props でデータを渡して宣言的に書くことがReactの推奨スタイルです。useImperativeHandle は「どうしても命令的に操作しないといけない」場面の最終手段と考えてください。
まとめ
useImperativeHandleは親コンポーネントに公開する ref の内容をカスタマイズするフック- DOM ノード全体ではなく、必要なメソッドだけを公開できる
- React 19 以降は
forwardRefなしで使えるが、18 以前はforwardRefが必要 - 命令的な操作(フォーカス・スクロール・アニメーション)にのみ使い、props で代替できる場面では使わない