プラスボタンを押下した回数に応じて入力欄が増えていくページをつくるのにハマったのでメモ。
参考のページを取り込もうとしてハマったところやポイントと思うところだけ書いておきます。
繰り返しはmapを使う。for文でuseStateを複数生成したりしない。
input:text のvalue属性は書き換え用のuseStateのsetterを呼ぶ関数を作ってそれをinputタグのonChangeで呼び出す。valueにuseStateの値を書いただけだと、何も入力できなくなる。
入力欄の識別はname属性にmapのindexを文字列加工してname配列にする。
mapの中のJSXはdivタグで囲ってそこにkey={index}を属性として埋める。ないとwarningが出る。はじめdivタグじゃなくてフラグメント<>で括っていたらこのwarningが解消できなくてハマった。
typescriptではアイテムリストを定義する時 const[items,setItems] = useState([]); のようにuseStateに型引数を与えないとコンパイルエラーで動かない。このtypeの中身はmapの中で入力欄に紐づけたい値の型を書く。またこのtypeは配列タイプとして記述する。
import React, { Component, useState } from "react";
import { render } from "react-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faChevronRight,
faChevronLeft,
faCircle,
faCheckCircle,
faPlus,
} from "@fortawesome/free-solid-svg-icons";
const targetDom = document.getElementById("hoge_sample");
export const HogeSample = () => {
// Itemが1ユニット。
type ItemsProps = {
message:string,
}[];
const[items,setItems] = useState<ItemsProps>([]);
const [inputValue, setInputValue] = useState('');
//クリック時にitems配列に新しいitemを作る処理
const handleAddButtonClick = () => {
//作られるitemの定義
const newItem = {
message: inputValue,
};
//items配列にpushされる
const newItems = [...items, newItem];
//useStateのitemsに反映
setItems(newItems);
};
// メッセージのテキストボックスの値が変わったら発火
const handleChangeMessage = (index:number,message:string) => {
//itemsを展開した配列、newItemsを作る
const newItems = [...items];
//テキストを更新する。
newItems[index].message = message;
setItems(newItems);
};
return (
<>
<FontAwesomeIcon
icon={faPlus}
onClick={() => handleAddButtonClick()}
/>
{items.map((item,index) => (
<div key={index}>
<input
type="text"
name={'message[' + index +']'}
value={item.message}
onChange={(event) => handleChangeMessage(index,event.target.value)}
/>
</div>)
)}
</>
);
};
if (targetDom != null) {
render(<HogeSample />, targetDom);
}
参考
【 React Hooks入門】useStateを使って買い物リストを作るチュートリアル
↧