todoアプリ作成
参考サイト:
https://www.youtube.com/watch?v=nRCNL9T3J98
ノードjsインストール確認、Reactひな型作成
PS C:\Users\…\react-project> node -v
v18.17.1
PS C:\Users\…\react-project> npx create-react-app react-tutorial
→完了するとHappy hacking!の表示
不要なファイルの削除\src\App.test.js src\logo.svg \src\reportWebVitals.js \src\setupTests.js
コンポーネントの作成
▼\src\TodoList.jsを作成
VSCodeプラグインES7+ React/Redux/React-Native をインストールしていればrafceタブ補完と入力すれば下記のように関数コンポーネントが入力されます
import React from 'react'
export const TodoList = () => {
return (
<div>TodoList</div>
)
}
▼App.jsを編集
インポートの記載
import { TodoList } from "./TodoList";
function App() {
return (
<div className="App">
<TodoList />
</div>
);
}
export default App;
入力欄、ボタン作成
▼.js
import TodoList from "./TodoList";
function App() {
return (
<div className="App">
<div>
<TodoList />
<input type="text" />
<button>タスクを追加</button>
<button>完了したタスクの削除</button>
<div>残りのタスク:0</div>
</div>
</div>
);
}
export default App;
1)useStateで状態を監視→変更で再レンダリング
2)propsでtodos={todos}でコンポーネント間のデータの受け渡し
▼App.js
import { useState } from "react";
import TodoList from "./TodoList";
function App() {
const [todos, setTodos] = useState(["Todo1", "Todo2"]);
return (
<div className="App">
<div>
<TodoList todos={todos}/>
<input type="text" />
<button>タスクを追加</button>
<button>完了したタスクの削除</button>
<div>残りのタスク:0</div>
</div>
</div>
);
}
export default App;
useState()
useState()
は、関数コンポーネントでstateを管理(state
の保持と更新)
state
とはコンポーネントが内部で保持する「状態」
▼TodoList.js
import React from 'react'
const TodoList = ({ todos }) => {
return (
<div>{todos}</div>
)
}
export default TodoList
Todo.jsを作成(各タスクをコンポーネントにおきかえる)
▼TodoList.js
import React from 'react';
import Todo from './Todo';
const TodoList = ({ todos }) => {
return todos.map((todo) => <Todo todo={todo} />);
}
export default TodoList
▼Todo.js
import React from 'react'
const Todo = ({ todo }) => {
return (
<div>{todo}</div>
)
}
export default Todo
todoをオブジェクトとして管理
▼App.js
function App() {
const [todos, setTodos] = useState([
{ id: 1, name: "Todo1", completed: false },
]);
▼Todo.js
const Todo = ({ todo }) => {
return (
<div>{todo.name}</div>
)
}
チェックボックスの実装(チェックオンオフは後から実装)
▼Todo.js
<div>
<label>
<input type="checkbox" checked={todo.completed} readOnly />
</label>
{todo.name}
</div>
タスクの追加
useRefで要素の取得(オブジェクトにおけるスプレッド構文の追加)
▼useRefで取得した内容をconsole.log()で確認
▼App.js
import { useState, useRef } from "react";
import TodoList from "./TodoList";
function App() {
const [todos, setTodos] = useState([
{ id: 1, name: "Todo1", completed: false },
]);
// useRefでinputの値を取得
const todoNameRef = useRef();
// タスクを追加する
const handleAddTodo = () => {
const name = todoNameRef.current.value;
// 空白のタスクを生成しない
if(name === "") return;
// setTodosでTodosの内容を更新
// オブジェクトにおけるスプレッド構文の追加
setTodos((prevTodos) => {
return [...prevTodos, { id: "1", name: name, completed: false }];
});
todoNameRef.current.value = null;
};
return (
<div className="App">
<div>
<TodoList todos={todos}/>
<input type="text" ref={todoNameRef} />
<button onClick={handleAddTodo}>タスクを追加</button>
<button>完了したタスクの削除</button>
<div>残りのタスク:0</div>
</div>
</div>
);
}
export default App;
対応)Warning: Each child in a list should have a unique “key” prop.
uuidインストール
ユニークキーの生成が可能
https://www.npmjs.com/package/uuid
▼npm install uuid
→package.jsonにてインストールの確認ができます
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"uuid": "^9.0.1",
"web-vitals": "^2.1.4"
},
▼App.jsを編集
import { useState, useRef } from "react";
import { TodoList } from "./TodoList";
import { v4 as uuidv4 } from 'uuid';
function App() {
const [todos, setTodos] = useState([
{ id: 1, name: "Todo1", competed: false }
]);
const todoNameRef = useRef();
const handleAddTodo = () => {
// タスクを追加
const name = todoNameRef.current.value;
setTodos((prevTodos) => {
return [...prevTodos, { id: uuidv4(), name: name, completed: false }]
});
todoNameRef.current.value = null;
};
▼TodoList.jsを編集
export const TodoList = ({ todos }) => {
return todos.map((todo) => <Todo todo={todo} key={todo.id}/>);
}
初期値をから行列にApp.js
function App() {
const [todos, setTodos] = useState([]);
toggleTodoでチェックボックスを管理
▼App.jsを編集
// チェックボックスの操作
const toggleTodo = (id) => {
// 直接値を変更しない為newTodosにコピーしている
const newTodos = [...todos];
// 引数のidとtodoのidが一致したら、completedを反転
const todo = newTodos.find((todo) => todo.id === id);
todo.completed = !todo.completed;
setTodos(newTodos);
};
return (
<div className="App">
<div>
<TodoList todos={todos} toggleTodo={toggleTodo} />
<input type="text" ref={todoNameRef} />
<button onClick={handleAddTodo}>タスクを追加</button>
<button>完了したタスクの削除</button>
<div>残りのタスク:0</div>
</div>
</div>
);
}
export default App;
▼TodoList.jsを編集
const TodoList = ({ todos, toggleTodo }) => {
return todos.map((todo) => <Todo todo={todo} key={todo.id} toggleTodo={toggleTodo} />);
}
▼Todo.jsを編集
import React from 'react'
const Todo = ({ todo, toggleTodo }) => {
const handleTodoClick = () => {
toggleTodo(todo.id);
};
return (
<div>
<label>
<input
type="checkbox"
checked={todo.completed}
readOnly
onClick={handleTodoClick}
/>
</label>
{todo.name}
</div>
)
}
export default Todo
残りのタスクの数をいれる
▼App.jsを編集
<div className="App">
<div>
<TodoList todos={todos} toggleTodo={toggleTodo} />
<input type="text" ref={todoNameRef} />
<button onClick={handleAddTodo}>タスクを追加</button>
<button>完了したタスクの削除</button>
<div>残りのタスク:{todos.filter((todo) => !todo.completed).length}</div>
</div>
</div>
完了したタスクの削除
// 完了したタスクの削除
const handleClear = () => {
const newTodos = todos.filter((todo) => !todo.completed);
setTodos(newTodos);
}
return (
<div className="App">
<div>
<TodoList todos={todos} toggleTodo={toggleTodo} />
<input type="text" ref={todoNameRef} />
<button onClick={handleAddTodo}>タスクを追加</button>
<div>残りのタスク:{todos.filter((todo) => !todo.completed).length}</div>
<button onClick={handleClear}>完了したタスクの削除</button>
</div>
</div>
);
}
レンタルサーバで公開
参考サイト:https://zenn.dev/kiriyama/articles/538face511307d
▼package.jsonを編集
{
"homepage": "https://xx/",
▼\public.htaccessを作成(publickフォルダに「.htaccess」のファイルを作成)
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
▼プロジェクトディレクトリで下記のコマンドでビルド
npm run build
buildというフォルダが作成されるので、その中身をFTPでアップロード
アップロードしたサイト:https://internet.mints.ne.jp/react-todo/