React 19で、forwardRefを使わずにrefを受け取る方法
React 19 では、関数コンポーネントが ref をほかの props と同じように受け取れます。そのため、新しく書くコンポーネントでは forwardRef で包む必要がなくなりました。forwardRef 自体は React 19 でも動き、将来のバージョンで非推奨になる予定です。
筆者は検証環境で、同じ TypeScript(.tsx)のコンポーネントを React 19 と React 18 の両方で動かし、親から渡した ref がどこにつながるかを確かめました。その結果と、公式ドキュメントに書かれている変更点をまとめます。
検証環境は Ubuntu 24.04、Node.js 22.22.0 です。React 19 側は react / react-dom 19.3.1、@types/react 19.3.0、typescript 7.0.2、比べる React 18 側は react / react-dom 18.3.1 です。どちらも esbuild 0.28.2 で変換し、jsdom 29.1.1 の上で描画しました。.tsx は tsc で型チェックしています。GIF は Playwright 1.56.1 の Chromium で撮りました。
React 19 では ref を props から取り出すだけ
React 19 の発表記事によると、React 19 からは関数コンポーネントで ref を props として読めます。検証では、次の MyInput を用意しました。forwardRef は使わず、分割代入で ref を取り出して <input> に渡すだけです。
import type { Ref } from 'react';
type Props = { placeholder?: string; ref?: Ref<HTMLInputElement> };
export function MyInput({ placeholder, ref }: Props) {
return <input placeholder={placeholder} ref={ref} />;
}
親から ref を渡して描画し、ref.current の中身と、ref.current.focus() で入力欄にフォーカスが移ったかを調べました。同じファイルを React 18 でも変換して動かしています。
react 19.3.1
MyInput: ref.current=<input> focused=true
react 18.3.1
MyInput: ref.current=null focused=false
console.error: Warning: MyInput: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)
console.error: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
React 19 では、ref.current が <input> になり、フォーカスも移りました。React 18 では ref.current は null のままで、「ref は props ではない」「関数コンポーネントには ref を渡せない。forwardRef を使うつもりか」という2つの警告が出ました。
同じ MyInput を Chromium で動かし、ボタンを3回押して ref.current.focus() を呼んだ様子がこちらです。上が React 18、下が React 19 です。

forwardRef は React 19 でもそのまま動く
これまでの書き方は、forwardRef の2つ目の引数で ref を受け取る形でした。
import { forwardRef } from 'react';
type Props = { placeholder?: string };
export const MyInputForwardRef = forwardRef<HTMLInputElement, Props>(
function MyInputForwardRef({ placeholder }, ref) {
return <input placeholder={placeholder} ref={ref} />;
},
);
このコンポーネントは、React 19.3.1 でも React 18.3.1 でも ref.current=<input> focused=true になりました。React 19.3.1 の開発用ビルドで動かしても、forwardRef を使ったことへの警告は出ませんでした。
forwardRef のリファレンスの冒頭には、「React 19 では forwardRef はもう必要ない。代わりに ref を props として渡す」「forwardRef は将来のリリースで非推奨になる」と書かれています。発表記事も、将来のバージョンで非推奨にして取り除くとしています。今すぐ書き換えなくても壊れませんが、新しく書くコンポーネントでは使わないほうがよい、という位置づけです。
書き換えには、公式の react-codemod に remove-forward-ref という codemod があります。README に載っているコマンドは npx codemod react/19/remove-forward-ref --target <path> です。検証環境では codemod のレジストリからパッケージを取得できず、実行できませんでした。そのため、変換結果は確かめていません。
React 18 では、ref を props で受け取る書き方は動きません。React 18 でも使われるライブラリのコンポーネントは、forwardRef を残す必要があります。
useImperativeHandle と memo でも ref は props で届く
DOM そのものではなく、決めたメソッドだけを親に見せたいときは useImperativeHandle を使います。useImperativeHandle のリファレンスは、React 19 からは props で受け取った ref をそのまま渡す書き方になっています。
import { useImperativeHandle, useRef, type Ref } from 'react';
export type FancyInputHandle = { focus: () => void; clear: () => void };
export function FancyInput({ ref }: { ref?: Ref<FancyInputHandle> }) {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
clear: () => {
if (inputRef.current) inputRef.current.value = '';
},
}), []);
return <input ref={inputRef} defaultValue="hello" />;
}
React 19 では、親の ref.current が { focus, clear } のオブジェクトになり、focus() でフォーカスが移り、clear() で入力欄が空になりました。React 18 では ref.current は null でした。
memo で包んだコンポーネント(memo(function MemoInput({ placeholder, ref }: Props) { ... }))も試しました。React 19 では ref.current=<input> になり、React 18 では null でした。memo で包んでも、React 19 なら ref は props として中のコンポーネントに届きます。
TypeScript では ref を props の型に書く
関数コンポーネントで ref を受け取るときは、props の型に ref?: Ref<HTMLInputElement> のように書きます。<input> の props をまとめて受け取る ComponentProps<'input'> を使う場合は、自分で書き足さなくても、型に ref が入っています。検証では、props: ComponentProps<'input'> で受け取って <input {...props} /> に渡すだけのコンポーネントで、React 19 では ref.current=<input> になりました。
ref を受け取らないコンポーネントに ref を渡すとどうなるかも確かめました。React 19.3.1 では、ref.current が null のままで、警告は何も出ませんでした。React 18 で MyInput に出たような「関数コンポーネントには ref を渡せない」という警告はありません。
一方、tsc はこの誤りを見つけます。ref を型に書いていないコンポーネントに渡した行(13行目)がエラーになりました。<div> 用の ref を、MyInput に渡した行(14行目)と、ComponentProps<'input'> で受け取るコンポーネントに渡した行(15行目)もエラーです。15行目のエラーからも、ComponentProps<'input'> の ref が <input> 用の型になっていることが分かります。次の出力は、14行目と15行目のエラーの続きの説明(3行ずつ)を省いています。
src/TypeError.tsx(13,19): error TS2322: Type '{ ref: RefObject<HTMLInputElement | null>; }' is not assignable to type 'IntrinsicAttributes & { placeholder?: string | undefined; }'.
Property 'ref' does not exist on type 'IntrinsicAttributes & { placeholder?: string | undefined; }'.
src/TypeError.tsx(14,16): error TS2322: Type 'RefObject<HTMLDivElement | null>' is not assignable to type 'Ref<HTMLInputElement> | undefined'.
src/TypeError.tsx(15,22): error TS2322: Type 'RefObject<HTMLDivElement | null>' is not assignable to type 'Ref<HTMLInputElement> | undefined'.
React 19.3.1 では、ref を使わないコンポーネントに ref を渡しても、実行時の警告は出ませんでした。ref.current が null のまま気づきにくいので、props の型に ref を書いて tsc に確かめさせると安心です。
クラスコンポーネントはそのまま、element.ref は非推奨に
クラスコンポーネントは、これまでどおりです。発表記事の注記のとおり、クラスに渡した ref はインスタンスを指すため、props には入りません。検証でも、React 19 と React 18 のどちらでも、親の ref.current はクラスのインスタンスで、this.props.ref は undefined でした。
もう1つ変わったのが、JSX の要素オブジェクトから ref を読む場合です。React 19 のアップグレードガイドによると、element.ref は非推奨になり、element.props.ref を使います。検証では、React 19 で element.props.ref に渡した ref が入っていました。element.ref も同じ ref を返しましたが、読んだときに次のエラーが記録されました。
console.error: Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.
React 18 では、element.props.ref には入らず、element.ref だけが ref を返しました。子の要素を調べて ref を取り出すようなコードは、React 19 では element.props.ref に直す必要があります。
forwardRef はいらなくなったのか
検証と公式ドキュメントから分かったことを、場合ごとに分けると次のとおりです。
| 場合 | forwardRef |
|---|---|
| React 19 で新しく書く関数コンポーネント | いらない。ref を props で受け取る |
| React 19 に上げた既存のコンポーネント | そのまま動く。将来の非推奨に備えて書き換えてよい |
| React 18 でも使われるコンポーネント | まだ必要。React 18 では props の ref は届かない |
| クラスコンポーネント | もともと使わない。ref はインスタンスを指す |
React 19 だけを対象にするなら、forwardRef は書かなくてよくなりました。書き換えるときは、props の型に ref を足し、tsc で渡し間違いがないかを確かめるのが、検証で分かった手堅い進め方です。





