Reactでformを作ってみる。

## form周りのパーツ
formにはテキストの入力、セレクトボックス、ラジオボタンなど様々な要素があります。
Reactで作成する際にはどのようにして作るのかを実際のコードと一緒に紹介します。

### input
#### 完成イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/844e15a4-8fe5-295c-9321-342e8f6bec12.png" width="250">


#### コード

```js
const InputText = () => {
  // 入力欄の状態変数`inputTextValue`と
  // 状態を変更するための関数`setInputTextValue`を定義する
  // 初期値は空にしておく
  const [inputTextValue, setInputTextValue] = useState('');

  // 上記と同様で変数と関数を定義し、初期値の文字列を定義
  const [text, setText] = useState('React');

  //入力状態を更新するイベントハンドラ
  const handleChange = (e) => setInputTextValue(e.target.value);

  //inputを空にして、テキストを更新する
  const handleClick = () => {
    setText(inputTextValue);
    setInputTextValue('');
  }

  return (
    <div>
      <p>はじめまして　{text}!</p>
      <input type='text' value={inputTextValue} onChange={handleChange} />
      <input type='buttton' value='入力' onClick={ handleClick } />
    </div>
  );
};
```
入力し、ボタンを押すと初期値の`React`の文字が入力した文字に置きかわります。
ただ、このコードには下記の箇所に1点問題があります。

```js
<input type='buttton' value='入力' onClick={ handleClick } />
```
このままだと

```
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`.
```
というエラーが出ます。
これは「onChangeハンドラなしでフォームフィールドにvalueプロパティを定義した場合に発生します。
このエラーは`defaultValue`を定義して解決しました。

```js
<input type='buttton' defaultValue='入力' onClick={ handleClick } />
```

### select
selectは`map()`関数を利用して作成します。

#### 完成イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/6e50faf1-cc40-84b8-77ed-dc2b1a377852.png" width="250">

#### コード
```js
const values = [
  { id: 1, item: 'item01' },
  { id: 2, item: 'item02' },
  { id: 3, item: 'item03' }
];

// map()関数を使ってoptionをvaluesで定義した要素分を生成
const SelectItems = values.map((value) => {
  return (
    <option value={value.item} key={value.id}>
      {value.item}
    </option>
  );
});

const InputSelectBox = () => {
  // 初期値をvaluesで定義した1つ目のitemに設定する
  const [selectedValue, setSelectedValue] = useState(values[0]['item']);

  const handleChangeSelectBox = (e) => {
    setSelectedValue(e.target.value);
  };

  return (
    <div>
      <p>{selectedValue}</p>
      <select value={selectedValue} onChange={handleChangeSelectBox}>
        {SelectItems}
      </select>
    </div>
  );
};
```

### radio

#### 完成イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/1a8717c4-ef16-93bb-c7a2-94a0c661b0bc.png" width="250">



#### コード
radioも基本的にはセレクトボックスと一緒ですが、labelに対してchangeイベントを設定するため親要素から子要素のlabelに値をchangeイベントや値を渡せるようにしてあげる必要があります。

```js
// ラジオボタンにセットしたい項目を定義
const radioValues = [
  { id: 1, item: '白' },
  { id: 2, item: '黒' },
  { id: 3, item: 'グレー' },
];

// 親要素のInputRadioからchangeイベントとcheckedのステータスを受け取れるようにする
const RadioItems = ({ onChange, checked }) =>
  radioValues.map((value) => {
    return (
      <label key={value.id}>
        <input
          type='radio'
          value={value.item}
          onChange={onChange}
          checked={checked === value.item}
        />
        {value.item}
      </label>
    );
  });


const InputRadio = () => {
  const [checkedValue, setCheckedValue] = useState(radioValues[0]['item']);
  const handleChangeRadio = (e) => setCheckedValue(e.target.value);

  return (
    <div>
      <p>現在選択されている値：{checkedValue}</p>
      <RadioItems onChange={handleChangeRadio} checked={checkedValue} />
    </div>
  );
};
```

チェックボックスは複数のチェック状態を管理するため上記の3つよ比べて少し複雑です。
長くなりそうなので次回にしたいと思います。