0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

タスク管理アプリの作成しながらReact勉強!(前半)

Posted at

はじめに

今日は、アプリを作成しながら、React・Redux・JavaScriptについて勉強してみたので、備忘録として残したいと思います!
私自身、Reactが苦手で、少しでも理解できたらなという思いで制作に取り組みました!

ということで、タスク管理アプリを作成しながらReact・Redux・JavaScriptについて理解を深めていきましょう!!

参考にしたコード

今回、タスク管理アプリを作成するに当たって、参考にさせて頂いたコードはこちらです!!
https://medium.com/wesionary-team/building-a-todo-app-using-react-redux-and-material-ui-688281d968ba

フォルダ構成(1部)

フォルダ構成は次のようになっています。
srcフォルダの中に、storeフォルダとTodoフォルダがあり、storeフォルダの中に、actionsフォルダとreducersフォルダがあります。
スクリーンショット 2020-08-29 11.46.52.png

actions

stateの値の変更を知らせるためのものです。
今回は、actionsフォルダの中のactionTypes.jsファイルでまとめて定義しています。

actionTypes.js
export const ADD_TODO = 'ADD_TODO';
export const EDIT_TODO = 'EDIT_TODO';
export const DELETE_TODO = 'DELETE_TODO';
export const SET_TITLE = 'SET_TITLE';
export const SET_TODO = 'SET_TODO';
export const SET_EDIT = 'SET_EDIT';
export const SET_ERROR = 'SET_ERROR';

このファイルでは、特に、なにもimportする必要はありません。
1行目から書き始めちゃってください!
本来、小規模なアプリだと上記のように、いちいち定数で定義する必要はないのですが、サンプルコードと合わせました。まあ、いずれ、大規模なアプリを作成する時に役立つ知識だと思います...

次にaction creatorを作っていきます。
action creatorっていうのは、actionを作るものです。

actions.js
import * as actionTypes from './actionTypes';
// actionTypes.jsで定義したactionをactionTypeとして、ここにimportしてる。

export const addTodo = () => {
    return {
        type: actionTypes.ADD_TODO,
    }
}

export const deleteTodo = (todo) => {
    return {
        type: actionTypes.DELETE_TODO,
        todo: todo
    }
}

export const editTodo = (todo) => {
    return {
        type: actionTypes.EDIT_TODO,
        todo: todo
    }
}

export const setTitle = (title) => {
    return {
        type: actionTypes.SET_TITLE,
        title: title
    }
}

export const setError = (error) => {
    return {
        type: actionTypes.SET_ERROR,
        error: error
    }
}

export const setTodo = (todo) => {
    return {
        type: actionTypes.SET_TODO,
        todo: todo
    }
}

export const setEdit = () => {
    return {
        type: actionTypes.SET_EDIT,
    }
}

ここまでは、大抵どのアプリでもそこまで大きく工程は変わりませんね。

reducer

では、reducerを作っていきます。reducerフォルダのindex.jsファイルに移動します。
reducerは、actionがdispatchによって送られてきて、その送られてきたactionを元にstateの更新処理を行います。
どのactionが送られてくるかはわからないので、caseによって異なる処理ができるようにしておきます。

index.js
import * as actionTypes from '../actions/actionTypes';

// stateの初期値
const initialState = {
    todos: [], // リスト部分に表示する、todo一覧の配列
    title: '', // 入力フォームの部分
    todo: '', // クリックされた値が一旦格納される部分
    edit: false, // setEditで、true/falseの切替
    error: '' // 警告文
}

const todos = (state = initialState, action) => {
    switch (action.type) {
        case actionTypes.ADD_TODO : // タスク追加のactionの場合
            const newTodo = { // 入力されたタスクを配列にする
                id: Date.now(),
                value: state.title,
            }
            return {
                ...state,
                todos: state.todos.concat(newTodo),
                /* 入力されたタスクが入っている配列newTodoとリスト部分の配列を 
                   合体させる。配列+配列は、concatメソッドを使う */
                title: '',
                error: ''
            }
        case actionTypes.DELETE_TODO : // タスク削除のactionの場合
            var newList = [...state.todos];
            var index = newList.indexOf(state.todo);
            if (index !== -1) {
            // indexOfで値が見つからなければ-1を返すから。
                newList.splice(index, 1);
                return {
                    ...state,
                    todos: newList
                }
            } else {
                return {
                    ...state
                }
            }
        case actionTypes.EDIT_TODO : // タスク編集のactionの場合
            newList = [...state.todos];
            index = newList.indexOf(state.todo);
            if (index !== -1) {
            // indexOfで値が見つからなければ-1を返すから。
                newList[index].value = state.title;
                // 見つかったindex番号の値を書き換えた分にする
                return {
                    ...state,
                    title: '',
                    edit: false, // 編集後は、falseに戻す
                    todos: newList,
                    error: ''
                }
            } else {
                return {
                    ...state
                }
            }
        case actionTypes.SET_TITLE : 
            return {
                ...state,
                title: action.title // titleに入力されたtitleを入れる
            }
        case actionTypes.SET_TODO :
            return {
                ...state,
                todo: action.todo,
                error: ''
            }
        case actionTypes.SET_ERROR :
            return {
                ...state,
                error: action.error
            }
        case actionTypes.SET_EDIT :
            return {
                ...state,
                edit: true, // 編集する時に、editをfalseからtrueに変える
                error: ''
            }
        default :
            return state;
    }
}

export default todos;

タスク入力フォームを作っていく

ここからは、表示部分を作っていく作業です。TodoフォルダのForm.jsに移動します。
今回は、デザインは、Material UIっていうのに頼ってます。
そのため、このMaterial UIをインストールする必要があります。
(インストール方法は割愛します。)

Form.js
import React from 'react';
import TextField from '@material-ui/core/TextField';
import { makeStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Container from '@material-ui/core/Container';
import Button from '@material-ui/core/Button';
import { connect } from 'react-redux';
import * as actionTypes from '../store/actions/actions';

const useStyles = makeStyles({
    root: {
        marginTop: 16,
        marginBottom: 16,
        padding: 16
    },
    button: {
        marginTop: 16
    }
});

const Form = ({ title, setTitle, addTodo, editTodo, edit, error, setError }) => {
    const classes = useStyles();
    const handleChange = (event) => {
        const title = event.target.value; 

        setTitle(title); //setTitleに引数で入力されたtitleを渡す
        if (title.length === 0) { // 入力されたtitleが0文字だったら...
            setError('入力してください。'); // エラー文を出力
        } else {
            setError(''); // 1文字以上入ってたら、エラー文は空欄
        }
    }

    const handleClick = () => {
        if (title.length === 0) {
            setError('入力してください。');
            return;
        }
        if (edit) { // クリックしたボタンがeditかどうか
            editTodo(); // editであれば、アクションeditTodo
        } else {
            addTodo(); // editでなければ、アクションaddTodo
        }
    }
    return (
        <Container maxWidth='sm' className={ classes.root }>
            <Grid container alignItems='center'>
                <Grid item md={ 12 }>
                    <TextField value={ title }
                     onChange={ handleChange } 
                     error={ !!error } helperText={ error } 
                     id='outlined-basic'
                     fullWidth label='Enter Task' multiline 
                     variant='outlined' />
                </Grid>
                <Grid item md={ 12 }>
                    <Button className={ classes.button } 
                     variant='contained' 
                     color='primary' onClick={ handleClick }>
                        {edit ? 'Edit' : 'Add' }
                    </Button>
                </Grid>
            </Grid>
        </Container>
    )
}

const mapStateToProps = (state) => { // propsへのstateの渡し方を決める
    return {
        title: state.title,
        edit: state.edit,
        error: state.error
    }
}

const mapDispatchToProps = dispatch => {
    return {
        setTitle: (title) => 
          dispatch(actionTypes.setTitle(title)),
        setError: (error) => 
          dispatch(actionTypes.setError(error)),
        addTodo: () => dispatch(actionTypes.addTodo()),
        editTodo: () => dispatch(actionTypes.editTodo())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Form);

今日は、ここまで!
次回は、追加されたタスクの表示部分の作成です!!

参考資料

参考にしたコード↓
Building a Todo app using React, redux and material-ui

コードの説明で、参考にしたQiita投稿↓
React Redux の難しかった点をできるだけシンプルに図解

actionsに関する公式の説明↓
Redux公式

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?