Reactでの入力フィールド操作

Reactでの入力フィールド操作は、ステートを介して行われます。 各入力フィールドには、そのvalueを含む独自のステートが割り当てられます。

例を見てみましょう。以下のような入力フィールドがあるとします:

jsxfunction App() {
  return <div>
    <input />
  </div>;
}

また、以下のようなステートがあるとします:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  return <div>
    <input />
  </div>;
}

入力フィールドのvalue属性にこのステートをバインドしてみましょう:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  return <div>
    <input value={value} />
  </div>;
}

この場合、ステートが変更されると、入力フィールドのテキストもリアクティブに更新されます。

しかし、これには興味深い副作用があります: ブラウザでコードを実行すると、入力フィールドのテキストを変更できなくなります!理由: 入力フィールドにテキストを入力しても、ステートvalueは変更されないため、 入力フィールドのテキストも変更されないはずだからです。

実際に試してみてください。私のコードをコピーして実行し、 入力フィールドのテキストを変更してみてください - 何も起こりません。 ブラウザのコンソールを開くと、Reactの警告が表示されます。 この警告は、ステートを入力フィールドにバインドしたことで、 入力フィールドがブロックされていることを示しています。

入力フィールドにテキストを入力できるようにしましょう。 そのためには、入力時にステートを入力フィールドの現在の値に変更する必要があります。

まず、入力フィールドにonChangeイベントを設定する必要があります:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  return <div>
    <input value={value} onChange={handleChange} />
  </div>;
}

このイベントは、Reactでは純粋なJavaScriptとは異なる動作をします。 Reactでは、入力フィールドが変更されるとすぐに発火します。 つまり、文字を入力または削除したときに発火します。

次に、このイベントのハンドラーを追加しましょう:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  function handleChange() {
    
  }
  
  return <div>
    <input value={value} onChange={handleChange} />
  </div>;
}

このハンドラーでは、入力フィールドの現在のテキストを読み取り、 setValue関数を使用してステートに設定する必要があります。

問題は、この関数のthisが入力フィールドを指さないことです - これはReactの特徴です。 イベントが発生した要素を取得するには、 event.targetを使用する必要があります:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  function handleChange(event) {
    console.log(event.target); // 入力フィールドのDOM要素への参照
  }
  
  return <div>
    <input value={value} onChange={handleChange} />
  </div>;
}

event.targetを使用して、入力フィールドの現在のテキストを出力してみましょう:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  function handleChange(event) {
    console.log(event.target.value); // 入力フィールドの現在のテキスト
  }
  
  return <div>
    <input value={value} onChange={handleChange} />
  </div>;
}

次に、入力フィールドのテキストをステートに書き込みましょう:

jsxfunction App() {
  const [value, setValue] = useState('text');
  
  function handleChange(event) {
    setValue(event.target.value);
  }
  
  return <div>
    <input value={value} onChange={handleChange} />
  </div>;
}

これで、入力フィールドにテキストを入力できるようになります。 この場合、ステートvalueには常に 入力フィールドの現在のテキストが含まれます。

これは簡単に確認できます。 テキストの内容を段落に出力してみましょう。 この場合、入力フィールドにテキストを入力すると、 入力したテキストが自動的に段落に表示されます:

jsxfunction App() {
  const [value, setValue] = useState('');
  
  function handleChange(event) {
    setValue(event.target.value);
  }
  
  return <div>
    <input value={value} onChange={handleChange} />
    <p>text: {value}</p>
  </div>;
}

無名のアロー関数を使用して、よりコンパクトなバージョンに書き換えることもできます:

jsxfunction App() {
  const [value, setValue] = useState('');
  
  return <div>
    <input value={value} onChange={event => setValue(event.target.value)} />
    <p>text: {value}</p>
  </div>;
}

したがって、任意の入力フィールドを動作させるには、以下の手順が必要です: その入力フィールド用のステートを作成し、 ステートを入力フィールドのvalue属性にバインドし、 入力フィールドにonChangeイベントを設定し、 イベントハンドラーで入力フィールドのステートをそのテキストに変更します。

これらの操作は、各入力フィールドに対して実行する必要があります。 つまり、2つの入力フィールドがある場合、 2つのステートと2つのonChangeイベントハンドラー関数を持つことになります。

Задание 1

2つの入力フィールドを作成してください。 最初の入力フィールドのテキストは最初の段落に出力され、 2番目の入力フィールドのテキストは2番目の段落に出力されるようにします。