コンテンツにスキップ

forwardRefの書き方

最終更新日: 2021-04-02
  • TS の情報に乏しく無駄にハマったのでメモ程度に

確認環境

Env Ver
React 17.0.1
TypeScript 4.1.3

サンプルコード

  • 今回はサンプルとして <input /> をラップしたコンポーネントのフォーカスを変更するために ref を使います

Child.tsx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { forwardRef } from 'react';

export type ChildProps = {
    type: 'text' | 'password' | 'number';
    onChange(changeValue: string): void;
};

// function 記法でないと ESLint が怒るので無効化
// eslint-disable-next-line react/display-name
export const Child = forwardRef<HTMLInputElement, ChildProps>(
    // このpropsに明示的な型定義がないと型エラーが出る
    (props: ChildProps, ref) => {
        const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
            props.onChange(ev.target.value);
        };

        return (
            <input
                ref={ref}
                type={props.type}
                onChange={(ev) => onChange(ev)}
            />
        );
    }
);

Parent.tsx

  • 下側の <Child /> だけフォーカスが行くようにしてます
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { useEffect, useRef } from 'react';
import { Child } from './Child';

export const Parent = () => {
    const ref = useRef<HTMLInputElement>(null);
    useEffect(() => {
        ref?.current?.focus();
    }, []);
    return (
        <ul>
            <li>
                <Child
                    type={'text'}
                    onChange={(ev) => console.log('top input', ev)}
                />
            </li>
            <li>
                <Child
                    ref={ref}
                    type={'text'}
                    onChange={(ev) => console.log('bottom input', ev)}
                />
            </li>
        </ul>
    );
};