LoginSignup
3
0

More than 1 year has passed since last update.

【React】useRefとforwardRefを両立する方法【関数コンポーネント】

Last updated at Posted at 2021-12-27

Reactで関数コンポーネントを作成する際、同じDOMノードに対して

を両立させたい場合があります。
その良い方法が見つかったので、ここに残しておきます。

useImperativeHandleを使います

気付いてみれば当たり前のことですが、useImperativeHandleを使えばうまく実装することができます。
useRefで保持しているDOMノードを、useImperativeHandleを使ってフォワーディングします。

const RefSample = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
    // DOMノードを保持するref
    const inputRef = useRef<HTMLInputElement>(null);
    // useImperativeHandleでフォワーディング
    useImperativeHandle(ref, () => inputRef.current!);

    const focusHandler = useCallback(() => {
        inputRef.current?.focus();
    }, []);
    return (
        <div>
            <button onClick={focusHandler}>focus</button>
            <input ref={inputRef} type={"text"} />
        </div>
    );
});

これで、このコンポーネントを使う際にrefを渡すことができるようになります。

const App = () => {
    const ref = useRef<HTMLInputElement>(null);
    const blurHandler = useCallback(() => {
        ref.current?.blur();
    }, []);
    return (
        <div>
            <RefSample ref={ref} />
            <button onClick={blurHandler}>blur</button>
        </div>
    );
};

補足: useImperativeHandleについて

useImperativeHandleの第2引数には関数を渡しますが、この関数がいつ実行されるのか公式ページには載っていないようなので、軽く調査しました。
どうやら、HTMLのレンダリングが終了してから、useLayoutEffectに渡した関数が呼び出されるまでの間のタイミングで、かつReactのUIツリーの末端にあるエレメントから実行されていくようです。

関連

これに関連して、以下の記事も作成しました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0