実施条件
[React][L1] Stateを用いてコンテンツ(li)を出力するを理解していること
環境
MacBook Pro (2.3 GHz 8コアIntel Core i9)
macOS 14.0(23A344)
Homebrew 4.3.8
gh 2.52.0
ソースコードの前に
フォルダ構成
├── package.json
├── public/
│ └── index.html
├── src/
│ ├── index.jsx
│ ├── Todo.jsx
│ └── styles.css
│
index.html
<!DOCTYPE html>
<html lang="en">
<head> </head>
<body>
<div id="root"></div>
</body>
</html>
index.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Todo } from "./Todo";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<Todo />
</StrictMode>
);
ソースコード
Todo.jsx(旧)
import { useState } from "react";
import "./styles.css";
export const Todo = () => {
const [incompleteTodos, setIncompleteTodos] = useState([
"TODOです1",
"TODOです2",
]);
const [completeTodos, setCompleteTodos] = useState([
"TODOでした1",
"TODOでした2",
]);
return (
<>
<div className="input-area">
<input placeholder="TODOを入力"></input>
<button>追加</button>
</div>
<div className="incomplete-area">
<p className="title">未完了のTODO</p>
<ul>
{incompleteTodos.map((todo) => {
return (
<li key={todo}>
<div className="list-row">
<p>{todo}</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
);
})}
</ul>
</div>
<div className="complete-area">
<p className="title">完了のTODO</p>
<ul>
{completeTodos.map((todo) => {
return (
<li>
<div className="list-row">
<p>{todo}</p>
<button>戻す</button>
</div>
</li>
);
})}
</ul>
</div>
</>
);
};
Todo.jsx
import { useState } from "react";
import "./styles.css";
export const Todo = () => {
+ const [todoText, setTodoText] = useState("");
const [incompleteTodos, setIncompleteTodos] = useState([
"TODOです1",
"TODOです2",
]);
const [completeTodos, setCompleteTodos] = useState([
"TODOでした1",
"TODOでした2",
]);
+ const onChangeTodoText = (event) => setTodoText(event.target.value);
return (
<>
<div className="input-area">
- <input placeholder="TODOを入力"></input>
+ <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText}></input>
<button>追加</button>
</div>
<div className="incomplete-area">
<p className="title">未完了のTODO</p>
<ul>
{incompleteTodos.map((todo) => {
return (
<li key={todo}>
<div className="list-row">
<p>{todo}</p>
<button>完了</button>
<button>削除</button>
</div>
</li>
);
})}
</ul>
</div>
<div className="complete-area">
<p className="title">完了のTODO</p>
<ul>
{completeTodos.map((todo) => {
return (
<li>
<div className="list-row">
<p>{todo}</p>
<button>戻す</button>
</div>
</li>
);
})}
</ul>
</div>
</>
);
};
解説
目的
-
input
タグ(テキストボックス)に入力された内容を、todoText
に入力(保持)する
コーディング
-
input
タグ(テキストボックス)に入力された内容を保持するState
(todoText
)を用意する
初期値は""
Todo.jsxexport const Todo = () => { + const [todoText, setTodoText] = useState(""); const [incompleteTodos, setIncompleteTodos] = useState([ "TODOです1", "TODOです2", ]); const [completeTodos, setCompleteTodos] = useState([ "TODOでした1", "TODOでした2", ]);
-
input
タグ(テキストボックス)に入力されたvalue
をState
(todoText
)と同期する
課題:todoText
の初期値は""
なので、更新できないTodo.jsxreturn ( <> <div className="input-area"> - <input placeholder="TODOを入力"></input> + <input placeholder="TODOを入力" value={todoText}></input> <button>追加</button> </div>
-
input
タグ(テキストボックス)に入力されたvalue
が変化したことを検知できるようにする
onChange
イベントを設定するTodo.jsxreturn ( <> <div className="input-area"> - <input placeholder="TODOを入力"></input> + <input placeholder="TODOを入力" value={todoText} onChange={}></input> <button>追加</button> </div>
-
onChange
イベントが発火した時に、todoText
を更新する関数(setTodoText
)が動くように実装する
event.target.value
については、Tips参照Todo.jsx+ const onChangeTodoText = (event) => setTodoText(event.target.value); return ( <> <div className="input-area"> - <input placeholder="TODOを入力"></input> + <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText}>
処理
- イベント
onChange
が発火する - 関数
onChangeTodoText
が起動する - 更新関数
setTodoText
の引数にevent.target.value
が入る -
State
todoText
にevent.target.value
が入り、更新される -
input
タグ(テキストボックス)に入力されたvalue
をState
(todoText
)に保持される
Tips
event.target.value
フォーム要素(例:
<input>
や<textarea>
)の値を取得するためによく使用されるプロパティです。event
はイベントオブジェクトであり、target
はイベントが発生した要素を指します。その中のvalue
プロパティが、フォーム要素に入力された現在の値を表します。
ここでは、event.target.value
を使用する関数onChangeTodoText
がセットされた<input>
でイベントが発生した場合、<input>
内のvalue
を取得する。