はじめに
- Reactで入力フォームを作る際、入力値をStateに設定するが、入力フォームが増えるとその分Stateを用意するのは面倒
- Stateの更新時にでプロパティ変数(
[プロパティ変数名]:値
)を使うことで、ひとつのStateで管理できるようになる。
手順解説
1.Stateの定義
- オブジェクトにして、各プロパティをフォーム要素にする
const [form, setForm] = useState({
feedId: data[0].id,
note: '',
});
2.フォームの定義
- value属性にStateのプロパティ値を設定する
- name属性をStateのプロパティ名と一致させる
- onChangeイベントに渡す関数は同じものにする
<select name="feedId" id="feedId" onChange={handleForm}>
{data.map((v) => (
<option key={v.id} value={v.id}>
{v.name}
</option>
))}
</select>
...
<input
type="text"
name="note"
value={form.note}
onChange={handleForm}
/>
3.Stateの設定(onChangeイベントの処理)
- Stateのプロパティ名と値が、フォームのnameとvalueに一致するため、プロパティ変数で汎用的に設定ができる。
const handleForm = (e) => {
setForm({
...form, // スプレッド構文でコピー
[e.target.name]: e.target.value, // 差分を設定する際、プロパティ変数を使用する。
});
};
実装例
プルダウンを変更すると一覧が切り替わるコンポーネントを作成する。(テキストボックスとプルダウンのフォーム値をStateと連動)
- サンプルデータ
list-data.json
[
{
"id": 1,
"name": "プルダウン1",
"list": [
{
"name": "リスト1-1",
"memo": "めも1-1"
},
{
"name": "リスト1-2",
"memo": "めも1-2"
}
]
},
{
"id": 2,
"name": "プルダウン2",
"list": [
{
"name": "リスト2-1",
"memo": "めも2-1"
},
{
"name": "リスト2-2",
"memo": "めも2-2"
}
]
}
]
コンポーネント
import { useState } from 'react';
import listData from '../../data/list-data.json';
export const PullDownAndList = () => {
const data = listData;
const [form, setForm] = useState({
feedId: data[0].id,
note: '',
});
const handleForm = (e) => {
setForm({
...form,
[e.target.name]: e.target.value,
});
};
// プルダウンの値(form.feedId)に応じた一覧でフィルタする
const fillerList = () => data.filter((d) => d.id === +form.feedId)[0].list;
return (
<div>
<select name="feedId" id="feedId" onChange={handleForm}>
{data.map((v) => (
<option key={v.id} value={v.id}>
{v.name}
</option>
))}
</select>
<div>
一括メモ:
<input
type="text"
name="note"
value={form.note}
onChange={handleForm}
/>
</div>
{fillerList().map((l) => (
<li key={l.name}>
{l.name} : {l.memo} : {form.note}
</li>
))}
</div>
);
};