はじめに
【2024年最新版】0からReactを勉強するならこのロードマップに従え!の記事を参考にReactの学習を進めています。今回は記事の課題1-3でデータ管理に迷ったのでその部分をまとめようと思います。
今回作ったもの
学習記録を管理するシンプルなアプリです
inputフォームに学習内容と学習時間を入力します

データの流れ
以下の流れでデータを管理しました:
フォーム状態の管理: [formData, setFormData]で入力値を制御
イベント処理: onClickでaddRecords関数を実行
状態更新: setRecordsでrecords配列にformDataで格納されたオブジェクトを追加
実装コード
型定義
HTMLのinput要素はtype="number"を指定しても、JavaScriptでは文字列として値を返すため、FormDataのtimeプロパティはstring型で定義しています。
setRecordsにformDataを渡すときにNumber(formData.time)としてnumber型に加工します。
type FormData = {
title: string;
time: string; // ←numberじゃない!
}
type Record = {
id: number;
title: string;
time: number;
}
状態管理
カウンター変数をrecordsのidに利用しています
let nextId = 0; // ID生成用
function App() {
const [records, setRecords] = useState<Record[]>([]);
const [formData, setFormData] = useState<FormData>({ title: "", time: "" });
}
データ追加の処理
一番わからなかった箇所かも。formDataとrecordsがどのようにして関わってくるのかが理解しにくかった。スプレッド構文(...records)で既存配列をコピーし、そこに新要素を追加した新しい配列を作成
const addRecords = () => {
setRecords([...records, {
id: nextId++,
title: formData.title,
time: Number(formData.time)
}]);
};
フォーム部分
input要素に入力された値をどのようにbutton要素に渡すのかがわからなかった。
<input
value={formData.title}
onChange={(e) => setFormData({...formData, title: e.target.value})}
/>
<button onClick={addRecords}>登録</button>
一覧表示
{records.map((record) => (
<div key={record.id}>
{record.title} - {record.time}時間
</div>
))}
まとめ
Reactの基本的なデータフローを実装することで、以下を理解できました:
・useStateでの状態管理
・イミュータブルな配列更新
・フォームのControlled Components
・TypeScriptでの型安全性
シンプルな機能でも、Reactの重要な概念がしっかり含まれていることを実感しました。
次はバリデーション機能を追加してみたいと思います。