#1 はじめに
2020年9月 現在
日本語でReact について検索すると、Class base で書かれた記事はよく見つかるけれど、react hooks を使って書かれた(関数)で書かれた記事が少ないと感じます。
海外サイトを見ていると、Reactの記述をClass baseで書いている人は、2020年9月 現在ほとんどいません。
記事が書かれた時期が2年前だとほとんどClass base ですが、、、(2018年11月 react hooks 発表前 or 直後)
現在は、React Hooksを使って関数で書くことが主流です。(簡潔に書けるから)
なので、これからReactを勉強する もしくは 勉強し始めの方は、React Hook を使ったアプリ制作を推奨します。
#2 概要
React hooks を 用いて、こんな感じのTodo アプリを作っていきます。
Todo を Create, Complete, Delete します。
・ github link : https://github.com/TokyoProgramming/todolist
ディレクトリ構成
+-- backend ...
|
|
|
+-- frontend
|
+-- src
|
+-- Components
| +-- Todo.js
| +-- Todo.css
| +-- TodoList.js
| +-- TodoList.css
|
+-- App.js
+-- App.css
+-- index.js
+-- index.css
#3 App.js
import React from 'react';
import './App.css';
import Todo from "./Components/Todo";
function App() {
return (
<div className="app">
<div className='body__card'>
<h1>My TodoList</h1>
<div className='body__todo'>
<Todo />
</div>
</div>
</div>
);
}
export default App;
4.Todo.js
import React, {useState} from 'react';
import './Todo.css';
import {TransitEnterexit} from "@material-ui/icons";
import TodoList from "./TodoList";
function Todo() {
const [todos, setTodos] = useState([])
const [value, setValue] = useState('')
//Create
const CreateTodo = (e) =>{
e.preventDefault();
// console.log('create new todos')
setTodos([...todos, { id: Math.random()*1000, text:value, isCompleted: false }]);
setValue('')
}
// Complete
const completeTodo = (id) => {
const done = todos.map(todo => {
if (todo.id === id) {
todo.isCompleted = !todo.isCompleted
}
return todo
})
setTodos(done)
};
// Delete
const deleteHandler = (id) => {
setTodos(todos.filter(todo => todo.id !== id))
} ;
return (
<div className="todo">
<div className='todo__body'>
<form
className="todo__input__form">
<TransitEnterexit/>
<input
className="todo__input"
value={value}
onChange={event => setValue(event.target.value)}
placeholder=" Set your todo . . . . ."
/>
<button
disabled={!value}
type="submit"
onClick={CreateTodo}>submit</button>
</form>
</div>
<div className='todo__todolist'>
<ul>
{todos.map(todo => (
<TodoList
todo={todo}
key={todo.id}
// 他のcomponentには、関数も引き渡すことができます。
completeTodo = {completeTodo}
deleteHandlers = {deleteHandler}
/>
))}
</ul>
</div>
</div>
)
}
export default Todo
react hooks の中で最もよく使うuseState
使用する際は、まず、import react, {useState} from 'react';
でuseState
をimport
します。
これを忘れると'useState' is not defined no-undef
のエラー表示がされてしまいます。
Todo.js
では、
const [todos, setTodos] = useState([])
const [value, setValue] = useState('')
2つのuseState
を定義しました。
(1) const [todos, setTodos] = useState([])
では、実際に作成するTodoを配列に格納していくためのものです。
例えば、以下のようにを書き換えるとわかりやすいと思います。
const[todos, setTodos] = useState([
{
id:1,
text: "todo1",
isCompleted: false
},
{
id:2,
text: "todo2",
isCompleted: false
},
])
(2)const [value, setValue] = useState('')
実際にTodoを作成するフォーム機能のための、useStateです。
公式:https://ja.reactjs.org/docs/hooks-reference.html#usestate
例えば、const [value, setValue] = useState('Yoooooo')
を記述すると、フォーム欄にあらかじめ、Yoooooo
と書かれています。
##・Todo 作成
//Create
const CreateTodo = (e) =>{
e.preventDefault();
// console.log('create new todos')
setTodos([...todos, { id: Math.random()*1000, text:value, isCompleted: false }]);
setValue('')
}
e.preventDefault()
,form
をsubmit
した際、ページがリフレッシュしません。
...
これで、配列をコピーします。めちゃめちゃシンプルですよね。
setTodos([配列をコピー, "追加"])
"追加"
: { id: Math.random()*1000, text:value, isCompleted: false }
id
は、uniqueIdでなければならないので、uuid
を使用する方法が一般的ですが、Math.random()
でランダムな数字を作成します。残りは、text:value
, isCompleted: false
を設定しておきます。
・Todo 完了
// Complete
const completeTodo = (id) => {
const done = todos.map(todo => {
if (todo.id === id) {
todo.isCompleted = !todo.isCompleted
}
return todo
})
setTodos(done)
};
map()
関数: https://ja.reactjs.org/docs/lists-and-keys.html#embedding-map-in-jsx
todo.isCompleted = !todo.isCompleted
選択した todo
のisCompleted
の逆にします。
##・Todo 削除
filter()
関数を使用します。
// Delete
const deleteHandler = (id) => {
setTodos(todos.filter(todo => todo.id !== id))
} ;
#5 TodoList.js
Todoで作成した、state
とfunction (関数)
を 渡していきます。
import React, {useState} from 'react';
import './TodoList.css';
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
import DoneIcon from '@material-ui/icons/Done';
import {Edit} from "@material-ui/icons";
function TodoList( {todo, completeTodo, deleteHandlers, updateHandler } ) {
return (
<div className="todoList">
<div
className='todolist__card'
style={{ textDecoration: todo.isCompleted ? "line-through" : "" }}
>
<DoneIcon
onClick={() => completeTodo(todo.id)}
/>
{(todo.isCompleted) ? (
<p className="doneTodo">{ todo.text }</p>
):(
<p>{ todo.text}</p>
)}
<DeleteForeverIcon
onClick={() => deleteHandlers(todo.id)}
/>
</div>
</div>
)
}
export default TodoList
あとは、cssを記述すると、上記のTodoアプリが出来上がります。
github link : https://github.com/TokyoProgramming/todolist