組み込みのブラウザ <input> コンポーネント は、さまざまな種類のフォーム入力をレンダーすることができます。

<input />

リファレンス

<input>

入力を表示するには、組み込みのブラウザ <input> コンポーネントをレンダーします。

<input name="myInput" />

さらに例を見る

Props

<input> は全ての共通要素である props をサポートしています。

以下の props を渡すことで、入力を制御することができます。

  • checked: ブール値。チェックボックス入力またはラジオボタンの場合、選択されているかどうかを制御します。
  • value: 文字列。テキスト入力の場合、そのテキストを制御します。(ラジオボタンの場合は、フォームデータを指定します。)

これらのいずれかを渡す場合、渡された値を更新する onChange ハンドラも渡す必要があります。

以下の <input> の props は、制御されていない入力にのみ関連しています。

以下の <input> props は、制御されていない入力と制御された入力の両方に関連します。

  • accept: 文字列。type="file" の入力によって受け取るファイルの種類を指定します。
  • alt: 文字列。type="image" の入力によって代替画像テキストを指定します。
  • capture: 文字列。type="file" 入力によってキャプチャされたメディア(マイク、ビデオ、またはカメラ)を指定します。
  • autoComplete: 文字列。可能なオートコンプリート動作の 1 つを指定します。
  • autoFocus: ブール値。true の場合、React はマウント時にその要素をフォーカスします。
  • dirname: 文字列。要素の文字方向性に対するフォームフィールド名を指定します。
  • disabled: ブール値。true の場合、入力はインタラクティブでなく、淡色表示されます。
  • children: <input> は子要素を受け取りません。
  • form: 文字列。この入力が属する <form>id を指定します。省略された場合、最も近い親フォームが対象となります。
  • formAction: 文字列。type="submit" および type="image" の親要素である <form action> を上書きします。
  • formEnctype: 文字列。type="submit" および type="image" の親要素である <form enctype> を上書きします。
  • formMethod: 文字列。type="submit" および type="image" の親要素である <form method> を上書きします。
  • formNoValidate: 文字列。type="submit" および type="image" の親要素である <form noValidate> を上書きします。
  • formTarget: 文字列。type="submit" および type="image" の親要素である <form target> を上書きします。
  • height: 文字列。type="image" の画像の高さを指定します。
  • list: 文字列。オートコンプリートオプションを持つ <datalist>id を指定します。
  • max: 数値。数値および日時入力の最大値を指定します。
  • maxLength: 数値。テキストおよびその他の入力の最大文字数を指定します。
  • min: 数値。数値および日時入力の最小値を指定します。
  • minLength: 数値。テキストおよびその他の入力の最小文字数を指定します。
  • multiple: ブール値。<type="file" および type="email" に複数の値を許可するかどうかを指定します。
  • name: 文字列。フォームで送信された入力の名前を指定します。
  • onChange: イベントハンドラ関数。制御された入力に必要です。ユーザが入力の値を変更するとすぐに起動します(例えば、キーストロークごとに起動します)。ブラウザの 入力のイベントと同じように作動します。
  • onChangeCapture: キャプチャフェーズで起動する onChange のバージョン。
  • onInput: イベントハンドラ関数。ユーザが値を変更するとすぐに起動します。歴史的な理由から、React では同様に動作する onChange を代わりに使用するのが慣用的です。
  • onInputCapture: キャプチャフェーズで起動する onInput のバージョン。
  • onInvalid: イベントハンドラ 関数。フォーム送信時の入力の検証に失敗した場合に起動します。組み込みの invalid イベントとは異なり、React の onInvalid イベントはバブリングします。
  • onInvalidCapture: キャプチャフェーズで起動する onInvalid のバージョン。
  • onSelect: イベントハンドラ 関数。<input> 内の選択が変更された後に起動します。React は onSelect イベントを拡張して、空の選択および編集時(選択に影響する可能性がある場合)にも起動します。
  • onSelectCapture: キャプチャフェーズで起動する onSelect のバージョン。
  • pattern: 文字列。value が一致する必要があるパターンを指定します。
  • placeholder: 文字列。入力値が空の場合は淡色で表示されます。
  • readOnly: ブール値。true の場合、ユーザは入力を編集できません。
  • required: ブール値。true の場合、フォームを送信するには値を指定する必要があります。
  • size: 数値。幅を設定と似ていますが、単位はコントロールによって異なります。
  • src: 文字列。type="image" 入力の、画像ファイルを指定します。
  • step: 正数または'任意の'文字列。有効な値間の距離を指定します。
  • type: 文字列。入力タイプの 1 つ。
  • width: 文字列。type="image" 入力の画像の幅を指定します。

注意事項

  • チェックボックスには value (または defaultValue) ではなく、checked (または defaultChecked) が必要です。
  • テキスト入力が文字列 value プロパティを受け取った場合、それは 制御されているものとして扱われます。
  • チェックボックスまたはラジオボタンがブール値の checked プロパティを受け取った場合、それは 制御されているものとして扱われます。
  • 入力を、同時に制御、非制御コンポーネントの両方にすることはできません。
  • 入力を、その存続期間内に、制御、非制御で切り替えることはできません。
  • すべての制御された入力には、その前の値を同期的に更新する onChange イベントハンドラが必要です。

使用法

様々なタイプの入力を表示する

入力を表示するには、<input> コンポーネントをレンダーします。デフォルトではテキスト入力になります。チェックボックスの場合は type="checkbox"、ラジオボタンの場合は type="radio"または他の入力タイプのいずれかを渡すことができます。

export default function MyForm() {
  return (
    <>
      <label>
        Text input: <input name="myInput" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" />
      </label>
      <hr />
      <p>
        Radio buttons:
        <label>
          <input type="radio" name="myRadio" value="option1" />
          Option 1
        </label>
        <label>
          <input type="radio" name="myRadio" value="option2" />
          Option 2
        </label>
        <label>
          <input type="radio" name="myRadio" value="option3" />
          Option 3
        </label>
      </p>
    </>
  );
}


入力にラベルを付ける

通常、すべての <input><label> タグ内に配置します。これにより、ブラウザに対してこのラベルがその入力に関連付けられていることを伝えます。ユーザがラベルをクリックすると、ブラウザは自動的に入力にフォーカスを当てます。これはアクセシビリティにも重要です。スクリーンリーダーは、ユーザが関連付けられた入力にフォーカスしたとき、ラベルのキャプションを読み上げます。

<input><label> にネストできない場合は、同じ ID を <input id><label htmlFor> に渡すことで関連付けます。また、同じコンポーネントの複数のインスタンス間の競合を避けるために、useId. を使用してそのような ID を生成します。

import { useId } from 'react';

export default function Form() {
  const ageInputId = useId();
  return (
    <>
      <label>
        Your first name:
        <input name="firstName" />
      </label>
      <hr />
      <label htmlFor={ageInputId}>Your age:</label>
      <input id={ageInputId} name="age" type="number" />
    </>
  );
}


入力の初期値を指定する

オプションで、入力の初期値を指定することができます。テキスト入力の場合は、defaultValue として文字列を渡します。チェックボックスとラジオボタンの場合は、代わりに defaultChecked ブール値を使用して初期値を指定します。

export default function MyForm() {
  return (
    <>
      <label>
        Text input: <input name="myInput" defaultValue="Some initial value" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
      </label>
      <hr />
      <p>
        Radio buttons:
        <label>
          <input type="radio" name="myRadio" value="option1" />
          Option 1
        </label>
        <label>
          <input
            type="radio"
            name="myRadio"
            value="option2"
            defaultChecked={true} 
          />
          Option 2
        </label>
        <label>
          <input type="radio" name="myRadio" value="option3" />
          Option 3
        </label>
      </p>
    </>
  );
}


フォーム送信時に入力値を読み取る

入力の周囲に、<form> を追加し、内部に <button type="submit"> を配置します。これにより、<form onSubmit> のイベントハンドラが呼び出されます。デフォルトでは、ブラウザはフォームデータを現在の URL に送信し、ページを更新します。e.preventDefault() を呼び出すことで、その動作を防ぐことができます。new FormData(e.target) を使用してフォームデータを読み込みます。

export default function MyForm() {
  function handleSubmit(e) {
    // Prevent the browser from reloading the page
    e.preventDefault();

    // Read the form data
    const form = e.target;
    const formData = new FormData(form);

    // You can pass formData as a fetch body directly:
    fetch('/some-api', { method: form.method, body: formData });

    // Or you can work with it as a plain object:
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson);
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        Text input: <input name="myInput" defaultValue="Some initial value" />
      </label>
      <hr />
      <label>
        Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
      </label>
      <hr />
      <p>
        Radio buttons:
        <label><input type="radio" name="myRadio" value="option1" /> Option 1</label>
        <label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2</label>
        <label><input type="radio" name="myRadio" value="option3" /> Option 3</label>
      </p>
      <hr />
      <button type="reset">Reset form</button>
      <button type="submit">Submit form</button>
    </form>
  );
}

補足

すべての <input>name を指定してください。例えば、<input name="firstName" defaultValue="Taylor" /> のようにします。{ firstName: "Taylor" } のように、指定した name は、フォームデータのキーとして使用されます。

落とし穴

デフォルトでは、<form> 内の 任意の <button> で送信されます。これは予期せぬ事態になることがあります。独自のカスタム Button React コンポーネントがある場合は、<button> の代わりに <button type="button"> を返すことを検討してみてください。そして、フォームを送信するためのボタンには、明示的に <button type="submit"> を使用してください。


状態変数を使用して入力要素を制御する

<input /> のような入力は制御されません<input defaultValue="Initial text" /> のように初期値を渡す場合でも、JSX は初期値を指定するだけで、現在の値を制御するものではありません。

controlled 入力をレンダーするには、それに value プロパティを渡します。(チェックボックスやラジオの場合は、checked React は、常に指定した value を入力が持つように強制します。通常、状態変数を宣言することによってこれを行います。

function Form() {
const [firstName, setFirstName] = useState(''); // Declare a state variable...
// ...
return (
<input
value={firstName} // ...force the input's value to match the state variable...
onChange={e => setFirstName(e.target.value)} // ... and update the state variable on any edits!
/>
);
}

制御された入力要素は、状態が必要な場合に意味があります。例えば、編集のたびに UI を再レンダーする必要がある場合などです。

function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
First name:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Your name is {firstName}.</p>}
...

また、制御された入力は、入力状態を調整するための複数の方法(例えば、ボタンをクリックすることによってなど)を提供したい場合にも役立ちます。

function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>

制御されたコンポーネントに渡す value は、undefinednull であってはなりません。初期値を空にしたい場合(例えば、以下の firstName フィールドのような場合)、状態変数を空の文字列('')で初期化してください。

import { useState } from 'react';

export default function Form() {
  const [firstName, setFirstName] = useState('');
  const [age, setAge] = useState('20');
  const ageAsNumber = Number(age);
  return (
    <>
      <label>
        First name:
        <input
          value={firstName}
          onChange={e => setFirstName(e.target.value)}
        />
      </label>
      <label>
        Age:
        <input
          value={age}
          onChange={e => setAge(e.target.value)}
          type="number"
        />
        <button onClick={() => setAge(ageAsNumber + 10)}>
          Add 10 years
        </button>
      </label>
      {firstName !== '' &&
        <p>Your name is {firstName}.</p>
      }
      {ageAsNumber > 0 &&
        <p>Your age is {ageAsNumber}.</p>
      }
    </>
  );
}

落とし穴

onChange を指定せずに value を渡すと、入力欄に入力することができなくなります。入力を value で制御すると、常に渡した値を強制的に持たせることになります。したがって、状態変数を value として渡したが、onChange イベントハンドラ内でその状態変数を同期的に更新し忘れると、React は入力をキーストロークごとに指定した value に戻してしまいます。


キーストロークごとの再レンダーを最適化する

制御された入力を使用する場合、キーストロークごとに状態が更新されます。状態を含むコンポーネントが大きなツリーを再レンダーすると、速度が遅くなる可能性があります。再レンダーのパフォーマンスを最適化する方法はいくつかあります。

例えば、キーストロークごとにすべてのページコンテンツを再レンダーするフォームがあるとします。

function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}

<PageContent /> は入力の状態に依存しないため、入力の状態を独自のコンポーネントに移動できます。

function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}

function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}

これにより、キーストロークごとに SignupForm のみが再レンダーされるため、パフォーマンスが大幅に向上します。

再レンダーを回避する方法がない場合(例えば、PageContent が検索入力の値に依存する場合)、useDeferredValue を使用することで、大規模な再レンダーの途中でも、制御された入力の応答性を維持できます。


トラブルシューティング

テキストを入力しても更新されない

value を指定して入力をレンダーし、onChange を指定しないと、コンソールにエラーが表示されます。

// 🔴 Bug: controlled text input with no onChange handler
<input value={something} />
Console
You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.

エラーメッセージが示すように、初期値を指定したいだけの場合は、代わりに defaultValue を渡してください。

// ✅ Good: uncontrolled input with an initial value
<input defaultValue={something} />

状態変数を使用してこの入力を制御したい場合は、onChange ハンドラを指定します。

// ✅ Good: controlled input with onChange
<input value={something} onChange={e => setSomething(e.target.value)} />

値を意図的に読み取り専用にする場合は、エラーを抑制するために readOnly プロパティを追加します。

// ✅ Good: readonly controlled input without on change
<input value={something} readOnly={true} />

チェックボックスをクリックしても更新されない

チェックボックスを checked だけでレンダーし、onChange が指定されていない場合、コンソールにエラーが表示されます。

// 🔴 Bug: controlled checkbox with no onChange handler
<input type="checkbox" checked={something} />
Console
You provided a checked prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultChecked. Otherwise, set either onChange or readOnly.

エラーメッセージが示すように、もし単に初期値を指定 したかった場合は、代わりに defaultChecked を渡します。

// ✅ Good: uncontrolled checkbox with an initial value
<input type="checkbox" defaultChecked={something} />

状態変数を使用してこのチェックボックスを制御したい場合は、onChange ハンドラを指定します。

// ✅ Good: controlled checkbox with onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />

落とし穴

チェックボックスの場合は、e.target.value ではなく e.target.checked を読み取る必要があります。

チェックボックスが意図的に読み取り専用である場合は、エラーを抑制するために readOnly プロパティを追加します。

// ✅ Good: readonly controlled input without on change
<input type="checkbox" checked={something} readOnly={true} />

入力カーソルがキーストロークごとに先頭にジャンプしてしまう

入力を制御する場合は、onChange を使用して、DOM からの状態変数を入力の値に更新する必要があります。

e.target.value (チェックボックスの場合は e.target.checked) 以外のものに更新することはできません。

function handleChange(e) {
// 🔴 Bug: updating an input to something other than e.target.value
setFirstName(e.target.value.toUpperCase());
}

非同期的に更新することもできません。

function handleChange(e) {
// 🔴 Bug: updating an input asynchronously
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}

コードを修正するには、それを e.target.value に同期的に更新します。

function handleChange(e) {
// ✅ Updating a controlled input to e.target.value synchronously
setFirstName(e.target.value);
}

これで問題が解決しない場合は、キーストロークごとに入力が DOM から削除され、再追加されている可能性があります。これは、再レンダーするたびに誤って状態をリセットしてしまっている場合に発生することがあります。例えば、入力またはその親の 1 つが常に異なる key 属性を受け取っている場合や、またはコンポーネント関数の定義をネストしている場合(この場合はサポートされておらず、「内部」コンポーネントが常に別のツリーとみなされます)などが挙げられます。


“A component is changing an uncontrolled input to be controlled” というエラーが表示される

コンポーネントに value を指定した場合、その value は存続期間を通じて常に文字列である必要があります。

React はコンポーネントを非制御にするか制御するかを認識できないため、最初に value={unknown} を渡し、後で value="some string" を渡すことはできません。制御されるコンポーネントは、null または unknown ではなく、常に文字列 value を受け取る必要があります。

もし value が API や状態変数から取得される場合、初期値が nullundefined になる可能性があります。その場合は、初期値として空の文字列('')を設定するか、value={someValue ?? ''} のようにして、value が文字列であることを確実にしてください。

同様に、チェックボックスに checked を渡す場合は、それが常にブール値であることを確認してください。