markdown

はじめに (対象読者・この記事でわかること)

この記事は、React を使って Web フロントエンド開発を行っている方、特に「input type=\"text\" の値をボタン操作でリセットしたい」と考えている初心者〜中級者を対象としています。
この記事を読むことで、以下のことができるようになります。

  • Controlled ComponentUncontrolled Component の違いを理解し、適切に選択できる
  • useStateuseRef を用いたシンプルなリセット実装方法をマスターできる
  • 余計な再レンダリングを防ぎつつ、フォームのクリア処理を安全に組み込める

React 開発で頻繁に出くわす「入力欄を初期化したい」シナリオにすぐに適用できる実装例と、実装時にハマりやすいポイントの対策も併せて紹介します。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。

  • HTML と CSS の基本的な知識
  • JavaScript(ES6 以降)の構文に慣れていること
  • React(関数コンポーネント、フック)の基礎的な理解

入力リセットの必要性と基本的考え方

Web アプリケーションでは、ユーザーが入力したテキストを クリア したいケースが多々あります。たとえば、検索フィールドの「リセット」ボタン、コメント投稿後の入力欄の消去、または「新規作成」画面での全項目初期化などです。
React では Controlled ComponentUncontrolled Component の二つのアプローチがあり、実装方法が大きく分かれます。

  • Controlled Componentvalue プロパティを状態 (state) と完全に同期させ、状態が変わるたびに再レンダリングが走ります。リセットは状態を空文字に戻すだけで完了しますが、状態管理が増える点に注意が必要です。
  • Uncontrolled Component は DOM の内部状態を直接操作し、React 側では ref で要素を参照します。リセットは ref.current.value = '' と書くだけで済み、状態管理が減りますが、値取得時に ref 経由になるためコードがやや散らかりやすいです。

どちらの方法も アクセシビリティ(フォーカス制御や ARIA 属性)を考慮すれば、ユーザー体験を損なわずに実装できます。次の章では、具体的なコード例と共に両アプローチの実装手順を詳しく解説します。

実装方法詳細とサンプルコード

この章では、実際に「テキスト入力をボタンでリセットする」機能を実装する手順を ステップ別 に示します。まずは Controlled Component での実装、続いて Uncontrolled Component での実装を行い、最後にハマりやすいポイントとその解決策をまとめます。

ステップ 1:プロジェクトのセットアップ

Bash
# npm または yarn で React プロジェクトを作成 npx create-react-app input-reset-demo cd input-reset-demo npm start

src/App.js を開き、以下のようにシンプルなコンポーネントを作成します。ここでは ControlledUncontrolled の二つのバージョンを同時に表示させ、比較しやすくしています。

Jsx
import React, { useState, useRef } from "react"; function ControlledInput() { const [text, setText] = useState(""); const handleReset = () => setText(""); return ( <div style={{ marginBottom: "1rem" }}> <h3>Controlled Input</h3> <input type="text" value={text} onChange={(e) => setText(e.target.value)} placeholder="ここに入力" /> <button onClick={handleReset}>リセット</button> </div> ); }

ステップ 2:Uncontrolled コンポーネントの実装

次に、useRef を使って DOM 要素へ直接アクセスする方式です。

Jsx
function UncontrolledInput() { const inputRef = useRef(null); const handleReset = () => { if (inputRef.current) { inputRef.current.value = ""; // 必要ならフォーカスも戻す inputRef.current.focus(); } }; return ( <div> <h3>Uncontrolled Input</h3> <input type="text" ref={inputRef} placeholder="ここに入力" /> <button onClick={handleReset}>リセット</button> </div> ); }

ステップ 3:全体を組み合わせる

Jsx
export default function App() { return ( <div style={{ padding: "2rem", fontFamily: "Arial, sans-serif" }}> <h2>React で input をボタンでリセットするデモ</h2> <ControlledInput /> <UncontrolledInput /> </div> ); }

これで起動しているアプリ上に、ControlledUncontrolled の2つの入力欄が表示され、各「リセット」ボタンをクリックすると即座にテキストがクリアされます。

ハマった点やエラー解決

発生した問題 原因 解決策
ボタンを押しても値が消えない value を状態と結びつけ忘れた(Controlled の場合) setText('') を正しく呼び出す
inputRef.currentnull になる コンポーネントがマウントされる前にリセット関数が走った handleReset をボタンの onClick にだけ紐付け、早期呼び出しを防止
再レンダリングが多くなりパフォーマンスが低下 大量の入力欄を Controlled で管理していた 必要に応じて Uncontrolled に切り替えるか、React.memo で子コンポーネントをメモ化
リセット後にフォーカスが外れる setState 後に自動的に再レンダーが走り、ブラウザのデフォルト挙動が発動 Uncontrolled の場合は focus() を明示的に呼び、Controlled の場合は useEffectref を使用

さらに洗練させるテクニック

  • カスタムフック useInputReset を作成すると、複数箇所で同じロジックを再利用できる。
  • フォーム全体のリセット では、react-hook-formreset() メソッドを活用すると、バリデーション状態まで一括クリアできる。
  • アクセシビリティ を考慮し、リセットボタンに aria-label="入力欄をクリア" を付与するとスクリーンリーダー利用者にも配慮できる。

まとめ

本記事では、React でテキスト入力を ボタン一つでリセット する方法を、ControlledUncontrolled の二つの視点から解説しました。

  • Controlled: useState で値を管理し、setState('') で即座にリセット
  • Uncontrolled: useRef 経由で DOM の value を直接書き換える
  • 実装時に陥りやすい「null 参照」や「再レンダリング過多」などの問題と、具体的な解決策を提示

これらの知識を活かすことで、フォームのクリア処理を安全かつ効率的に実装でき、ユーザー体験の向上につながります。次回は、react-hook-form と組み合わせた高度なバリデーション・リセットパターンについて解説する予定です。

参考資料