かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

React Hooks forwardRef を使わずに子コンポーネントにrefを渡す

React で子コンポーネントを ref で触りたい時、forwardRef APIを使うように言われます。

例えばボタンをクリックしたらフォーカスされるインプットフィールドだとこんな感じ。

import React, { useRef } from 'react';

const InputField = React.forwardRef({placeholder}, ref) => {
  return <input ref={ref} placeholder={placeholder} />
});

const App = () => {
  const inputRef = useRef(null);
  const onFocus = () => {
    inputRef.current.focus();
  };
  return (
    <>
      <InputField ref={inputRef} placeholder={forwardRef Input Field} />
      <button onClick={onFocus}>Focus</button>
    </>
  );
};

ref という名前で渡さなければ forwardRef API を使わなくても問題なく動作する

forwardRef を使わずに ref={ref} のような props を渡していると Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? という warning が発生するのですが、子コンポーネントに渡す props のキーが ref という名前でなければ warning も発生せず問題なく動作してしまうみたいです。

import React, { useRef } from 'react';

const InputField = ({placeholder, elmRef}) => {
  return <input ref={elmRef} placeholder={placeholder} />
};

const App = () => {
  const inputRef = useRef(null);
  const onFocus = () => {
    inputRef.current.focus();
  };
  return (
    <>
      <InputField elmRef={inputRef} placeholder={Input Field without forwardRef} />
      <button onClick={onFocus}>Focus</button>
    </>
  );
};

forwardRef API を使った方が速いとかあるのでしょうか?
チョット判らないのですが、これでも forwardRef を使った時と同じように問題なく動作します。

サンプル

See the Pen React forwardRef vs useRef by KIKIKI (@kikiki_kiki) on CodePen.

TypeScript だと渡される props は RefObject なのでこんな感じ

import React, { useRef, RefObject } from 'react';

type InputFieldProps = {
  placeholder: string;
  elmRef: RefObject<HTMLInputElement>
};

const InputField = ({placeholder, elmRef}: InputFieldProps) => {
  return <input ref={elmRef} placeholder={placeholder} />
};

const App = () => {
  const inputRef = useRef<HTMLInputElement>(null);
  const onFocus = () => {
    inputRef.current && inputRef.current.focus();
  };
  return (
    <>
      <InputField elmRef={inputRef} placeholder={Input Field without forwardRef} />
      <button onClick={onFocus}>Focus</button>
    </>
  );
};

おわり


マイ・インターン(字幕版)

マイ・インターン(字幕版)

  • 発売日: 2016/01/13
  • メディア: Prime Video
👆とても面白かったです