ボタンクリックで増やしたinputタグの入力値を、別ボタンクリック時にコンソールに出力させる処理をご紹介します。
今回はコンソールへの出力ですが、API通信を用いたデータ送信にも役立ちます。
import { useState } from 'react';
type Item = {
id: number;
textValue: string;
test3Value:string;
numberValue: number;
};
const App = () => {
const [items, setItems] = useState<Item[]>([]);
const addItem = () => {
const newItem: Item = {
id: items.length + 1,
textValue: '',
test3Value: '',
numberValue: 0,
};
setItems([...items, newItem]);
};
const handleInputChange = (id: number, value: string | number, type: 'text' | 'number' | 'test3') => {
const newItems = items.map((item) => {
if (item.id === id) {
if (type === 'text') {
return { ...item, textValue: value as string };
} else if (type === 'number') {
return { ...item, numberValue: value as number };
} else if (type === 'test3') {
return { ...item, test3Value: value as string };
}
}
return item;
});
setItems(newItems);
};
const confirmItems = () => {
console.log("Items:", items);
items.forEach(item => {
console.log(`Item ${item.id}: Text=${item.textValue}, Number=${item.numberValue} , test3Value=${item.test3Value}`);
});
};
return (
<div>
{items.map((item) => (
<div key={item.id}>
<input
type="text"
id={`item-text-${item.id}`}
value={item.textValue}
onChange={(e) => handleInputChange(item.id, e.target.value, 'text')}
/>
<input
type="number"
id={`item-number-${item.id}`}
value={item.numberValue}
onChange={(e) => handleInputChange(item.id, parseInt(e.target.value, 10) || 0, 'number')}
/>
<input
type="test3"
id={`item-text-${item.id}`}
value={item.test3Value}
onChange={(e) => handleInputChange(item.id, e.target.value, 'test3')}
/>
</div>
))}
<button onClick={addItem}>アイテム追加</button>
<button onClick={confirmItems}>アイテム確定</button>
</div>
);
};
export default App;
①使用するオブジェクトの型を定義
②アイテムを格納するステートを用意
③アイテムを追加する関数を作成
④増やしたフォーム要素の状態を管理するための関数を追加
⑤入力アイテムの状態をコンソールに出力する関数
今回データとして使用するオブジェクトの型を定義します。
type Item = {
id: number;
textValue: string;
test3Value:string;
numberValue: number;
};
①で定義したオブジェクトが格納されるためのステートを配列で用意します。
この配列の中に各種アイテムのデータが定義した①の型を元に格納される形となります。
const [items, setItems] = useState<Item[]>([]);
「アイテム追加」ボタンを押下した際に初期値の新しいアイテムをitemsの中に格納する関数を作成します。
①で定義したitem型を用いて、各種プロパティの初期値を設定し、itemsの中に新しいオブジェクトとして格納します。
const addItem = () => {
const newItem: Item = {
id: items.length + 1,
textValue: '',
test3Value: '',
numberValue: 0,
};
setItems([...items, newItem]);
};
各種inputタグの値が更新(onChange)された際に、引数としてid(番号),value(入力値),type(リテラル型)を取得し、
newItems配列に、現状のitemsに格納されているitemに対し、mapメソッドを用いてどのリテラル型に該当するかを仕分け、該当した型のvalue(入力値)を各種用意した初期値の入力値(type=“text”ならtextValueプロパティ)を更新し、変更を加えた配列を再構築します。
const handleInputChange = (id: number, value: string | number, type: 'text' | 'number' | 'test3') => {
const newItems = items.map((item) => {
if (item.id === id) {
if (type === 'text') {
return { ...item, textValue: value as string };
} else if (type === 'number') {
return { ...item, numberValue: value as number };
} else if (type === 'test3') {
return { ...item, test3Value: value as string };
}
}
return item;
});
setItems(newItems);
};
アイテム確定ボタン押下時に、items(配列)と、各種配列の中身をプレフィックスをつけてコンソールに出力します。
const confirmItems = () => {
console.log("Items:", items);
items.forEach(item => {
console.log(`Item ${item.id}: Text=${item.textValue}, Number=${item.numberValue} , test3Value=${item.test3Value}`);
});
};
ここまでが、returnより上に記述する処理の内容となります。
続いてtsx箇所について触れていきます。
・items配列(itemオブジェクトが格納されている配列)に対し、mapメソッドで出力を行い、フォームを出力します。
・包括要素に対してkey設定をします。
・該当要素のidにはidを、typeにはリテラル型を、valueにはitemの初期設定で設定したvalue値を、onChangeではhandleInputChange関数にid,入力値,リテラル型を取る形で記述します。
・type: numberのinputタグについては整数とするためparseIntメソッドを用いています。
・アイテム追加とアイテム確定ボタンを追加し、onClickに各種必要な挙動の関数を記述することで、動作します。
return (
<div>
{items.map((item) => (
<div key={item.id}>
<input
type="text"
id={`item-text-${item.id}`}
value={item.textValue}
onChange={(e) => handleInputChange(item.id, e.target.value, 'text')}
/>
<input
type="number"
id={`item-number-${item.id}`}
value={item.numberValue}
onChange={(e) => handleInputChange(item.id, parseInt(e.target.value, 10) || 0, 'number')}
/>
<input
type="test3"
id={`item-test3-${item.id}`}
value={item.test3Value}
onChange={(e) => handleInputChange(item.id, e.target.value, 'test3')}
/>
</div>
))}
<button onClick={addItem}>アイテム追加</button>
<button onClick={confirmItems}>アイテム確定</button>
</div>
);
以上で、inputタグの増やし方、それをコンソールに出力させる機能の実装ができました。
この機能は動的に増えるinputタグを実装する際に役立つかなと思います。