LoginSignup
1
1

More than 3 years have passed since last update.

React hooks を使ってTodoApp を作成する。

Last updated at Posted at 2020-09-20

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

Todolist_new_1

ディレクトリ構成

   +-- backend ...
   |
   |
   |
   +-- frontend
       |   
       +-- src 
            |   
            +-- Components
            |   +-- Todo.js
            |   +-- Todo.css
            |   +-- TodoList.js
            |   +-- TodoList.css
            |
            +-- App.js 
            +-- App.css
            +-- index.js
            +-- index.css

3 App.js

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

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';useStateimportします。
これを忘れると'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
    },
])

Todolist_hardcoded

(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(),formsubmitした際、ページがリフレッシュしません。
... これで、配列をコピーします。めちゃめちゃシンプルですよね。
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選択した todoisCompletedの逆にします。

・Todo 削除

filter()関数を使用します。

// Delete
    const deleteHandler = (id) => {
        setTodos(todos.filter(todo => todo.id !== id))
    } ;

5 TodoList.js

Todoで作成した、statefunction (関数)を 渡していきます。

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1