制作物
index.jsの記述
index.htmlのid="root"に対してレンダリングしてます。
React.StrictModeで囲んであげることで言葉通り厳格なモードとして脆弱性などがあればwariningやerrorを吐いてくれます。
AppコンポーネントによってApp.jsを呼び出す。
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
App.jsの記述
TodoListのコンポーネントを呼び出す。
rafceという拡張コマンドを打つことで関数コンポーネントを簡単に生成できる。
uuidv4を使用してkeyの重複回避。(UUID(v4) がぶつかる可能性を考えなくていい理由:
https://qiita.com/ta_ta_ta_miya/items/1f8f71db3c1bf2dfb7ea
)
コンポーネントごとに作成箇所を分けられるので複数人数開発がしやすいことはReactのメリット。
コンポーネントからの返却値は
import TodoList from "./TodoList";
import React, { useState, useRef } from "react";
import { v4 as uuidv4 } from "uuid";
function App() {
const [todos, setTodos] = useState([]);
const todoNameRef = useRef();
const handleAddTodo = (e) => {
// タスクを追加する。
const name = todoNameRef.current.value;
if (name === "") return;
setTodos((prevTodos) => {
return [...prevTodos, { id: uuidv4(), name: name, completed: false }];
});
todoNameRef.current.value = null;
};
const toggleTodo = (id) => {
const newTodos = [...todos];
const todo = newTodos.find((todo) => todo.id === id);
todo.completed = !todo.completed;
setTodos(newTodos);
};
const handleClear = () => {
const newTodos = todos.filter((todo) => !todo.completed);
setTodos(newTodos);
};
return (
<div>
<TodoList todos={todos} toggleTodo={toggleTodo} />
<input type="text" ref={todoNameRef}></input>
<button onClick={handleAddTodo}>タスクを追加</button>
<button onClick={handleClear}>完了したタスクの削除</button>
<div>残りのタスク:{todos.filter((todo) => !todo.completed).length}</div>
</div>
);
}
export default App;
useState
変数を監視するために使うHooks。
const [todos, setTodos] = useState([]);
usestate()で宣言したtodosという値が更新されたら追加したタイミングされたらそのタイミングで画面を再レンダリングされます。
変数が変わった時だけページをレンダリングできるので無駄な画面更新がない良さがあります。
todosは追加していくタスク
setTodos()で変動していくtodos(値)を保存していきます。
useStateは初期値をセットできる。
useRef
const todoNameRef = useRef();
これで宣言して
取得したいinput箇所にrefを追加して取得できるようになります。
どのtodoを実施したか判別
const newTodos = [...todos];
で宣言して値をコピーします。
ミュータブル、イミュータブルの概念からこれをすることが望ましいです。
find関数でどのtodoと一致するか判別して値をsetTodosで保存し直します。
const toggleTodo = (id) => {
const newTodos = [...todos];
const todo = newTodos.find((todo) => todo.id === id);
todo.completed = !todo.completed;
setTodos(newTodos);
};
完了タスクの削除
filterという関数を使います。
チェックが入っているものに関してはスルーさせます。
!todo.completed(todoが完了してない場合)の数をカウントするようになります。
const handleClear = () => {
const newTodos = todos.filter((todo) => !todo.completed);
setTodos(newTodos);
};
レンダリングで表示する側でもlengthでその数を表示させます。
<div>残りのタスク:{todos.filter((todo) => !todo.completed).length}</div>
TodoList.jsの記述
app.jsの下記の記述で変数を渡して
<TodoList todos={todos} toggleTodo={toggleTodo} />
TodoList.jの下記の記述で変数をもらっています。
TodoList = ({ todos, toggleTodo }) => {
map関数で配列の中のtodoを一つ一つ取り出してさらにTodoコンポーネントを呼び出す。
propsのバケツリレーになっていてあまり良い記述ではありません。
key部分にuuidv4を使ってユニークキーになるように設定。
import React from "react";
import Todo from "./Todo";
import { v4 as uuidv4 } from 'uuid';
const TodoList = ({ todos, toggleTodo }) => {
return todos.map((todo) => <Todo todo={todo} key={uuidv4()} toggleTodo={toggleTodo} />);
};
export default TodoList;
Todo.jsの記述
checked={todo.completed}
todoのチェックボックスの表示を監視されているオブジェクトのステータスを見て判断させます。
onChangeというトリガーを入れます。
import React from "react";
const Todo = ({ todo, toggleTodo }) => {
const handleTodoClick = () => {
toggleTodo(todo.id);
};
return (
<div>
<label>
<input type="checkbox" checked={todo.completed} readOnly onChange={handleTodoClick} />
</label>
{todo.name}
</div>
);
};
export default Todo;
参考
https://ja.reactjs.org/docs/components-and-props.html
https://qiita.com/ta_ta_ta_miya/items/1f8f71db3c1bf2dfb7ea
https://www.youtube.com/watch?v=nRCNL9T3J98