てらブログ

てらブログ

日々の学習の備忘録

forwardRefってなんだっけ

目的

下記コードを理解したかった。

import { ReactNode, forwardRef } from "react";

export const InputSelectBox = forwardRef<
  HTMLSelectElement,
  JSX.IntrinsicElements["select"] & {
    children: ReactNode;
  }
>((props, ref) => {
  return (
    <select
      {...props}
      ref={ref}
      className="XXX"
    >
      {props.children}
    </select>
  );
});

InputSelectBox.displayName = "InputSelectBox";

forwardRefについて

about

ドキュメントを読むと下記の記載がある。

forwardRef は、コンポーネントが親コンポーネントに DOM ノードを参照として公開することを可能にします。

つまり、コンポーネント内のDOMにRefオブジェクトを渡すための機能。refは特殊な属性らしく、propsとして渡したり、受け取ったりができない。そもそも関数コンポーネントにrefを渡すことはできない。

usage

const SomeComponent = forwardRef(render)

refを渡すことで、DOMを参照したり、外側から操作したりすることが可能。React Hook Formのregisterの利用にも◎

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  const { label, ...otherProps } = props;
  return (
    <label>
      {label}
      <input {...otherProps} ref={ref} />
    </label>
  );
});

forwardRef<refの対象, props>()で定義する。

参照:
ja.react.dev
ja.react.dev

最終的なコード

propsを明示的にし、型を外に出すようにリファクタリングした。

import { ReactNode, forwardRef } from "react";

type SelectProps = JSX.IntrinsicElements["select"] & {
  children: ReactNode;
};

export const InputSelectBox = forwardRef<HTMLSelectElement, SelectProps>(
  (props, ref) => {
    const { children, ...restProps } = props;
    return (
      <select
        {...restProps}
        ref={ref}
        className="rounded-md border border-gray-300 p-1 focus:border-blue-500 focus:ring-blue-500"
      >
        {children}
      </select>
    );
  },
);

InputSelectBox.displayName = "InputSelectBox";