LoginSignup
3
3

More than 3 years have passed since last update.

[Laravel+React] Todoアプリ チートシート

Last updated at Posted at 2019-09-06

Laravel5.7でReactを利用した開発をしてみるの記事をさらにコピペで実装できるように自分の備考録としてチートシートにまとめてみました。
初めてする方は上記記事に詳しく説明がまとめられておりますので、そちらを参照してください。

環境構築

Laravel環境構築 チートシート

手順

php artisan preset react
npm install && npm run dev
php artisan make:migration create_todos_table
database/migrations/xxxxx_create_todos_table.php
        // 中略
        Schema::create('todos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title')->nullable();
            $table->timestamps();
        });
        // 中略
php artisan migrate

php artisan make:model Todo

php artisan tinker
$todo1 = new App\Todo;
$todo1->title = 'Todo';
$todo1->save();
routes/web.php
Route::get('/{any}', function(){
    return view('welcome');
})->where('any','.*');
resouces/js/app.js
require('./components/TodoApp');
resouces/views/welcome.blade.php
<!doctype html>
<html lang="ja">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- CSS -->
    <link rel="stylesheet" href="{{ asset('css/app.css') }}">

    <title>react test</title>
</head>

<body>
    <div id="app">
        <div class="container">
            <h3 class="mt-5">Todo 管理システム</h3>

            <!-- ここを置き換えていく -->
            <div id="todoApp"></div>

        </div>
    </div>

<!-- avaScript -->
<script src="{{ asset('js/app.js')}}"></script>
</body>
</html>
routes/api.php
Route::group(['middleware' => 'api'], function(){
    Route::get('get', 'TodoController@getTodos');
    Route::post('add', 'TodoController@addTodo');
    Route::post('del', 'TodoController@deleteTodo');
});
php artisan make:controller TodoController
app/Http/Controllers/TodoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Todo;

class TodoController extends Controller
{
    //getTodos
    public function getTodos()
    {
        $todos = Todo::all();
        return $todos;
    }

    //add todo
    public function addTodo(Request $request)
    {
        $todo = new Todo;
        $todo->title = $request->title;
        $todo->save();

        $todos = Todo::all();
        return $todos;
    }

    //delete
    public function deleteTodo(Request $request)
    {
        $todo = Todo::find($request->id);
        $todo->delete();

        $todos = Todo::all();
        return $todos;
    }
}
resources/js/components/TodoApp.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

//RenderRowsの機能実装
function RenderRows(props){
    //mapでループしている(for相当)
    return props.todos.map(todo => {
        return (
            <tr key={todo.id}>
                <td>{todo.id}</td>
                <td>{todo.title}</td>
                <td>
                    <button 
                        className="btn btn-secondary" 
                        onClick={() => props.deleteTask(todo)}
                    >
                        完了
                    </button>
                </td>
            </tr>
        );
    });
}

export default class TodoApp extends Component {

    //コンストラクタ内でstateにtodosを宣言
    constructor(){
        super();
        this.state = {
            todos: [],
            todo: ''
        };
        this.inputChange = this.inputChange.bind(this);
        this.addTodo = this.addTodo.bind(this);
        this.deleteTask = this.deleteTask.bind(this);
    }

    //コンポーネントがマウントされた時点で初期描画用のtodosをAPIから取得
    componentDidMount(){
        axios
            .get('/api/get')
            .then((res) => {
                //todosを更新(描画がかかる)
                this.setState({
                    todos: res.data
                });
            })
            .catch(error => {
                console.log(error)
            })
    }

    //入力がされたら(都度)
    inputChange(event){
        switch(event.target.name){
            case 'todo':
                this.setState({
                    todo: event.target.value
                });
                break;
           default:
                break;
       }
    }

    //登録ボタンがクリックされたら
    addTodo(){
        //空だと弾く
        if(this.state.todo == ''){
            return;
        }

        //入力値を投げる
        axios
            .post('/api/add', {
                title: this.state.todo
            })
            .then((res) => {
                //戻り値をtodosにセット
                this.setState({
                    todos: res.data,
                    todo: ''
                });
            })
            .catch(error => {
                console.log(error);
            });
    }

    //完了ボタンがクリックされたら
    deleteTask(todo){
        axios
            .post('/api/del', {
                id: todo.id
            })
           .then((res) => {
                this.setState({
                    todos: res.data
                });
            })
            .catch(error => {
                console.log(error);
            });
    }

    //テーブルの骨組みを描画し、行の描画はRenderRowsに任せる(その際、todosを渡す)
    render() {
        return (
            <React.Fragment>
                <div className="form-group mt-4">
                    <label htmlFor="todo">新規Todo</label>
                    <input 
                        type="text" 
                        className="form-control" 
                        name="todo" 
                        value={this.state.todo} 
                        onChange={this.inputChange}
                        placeholder="Todoを入力してください"
                    />
                </div>
                <button className="btn btn-primary" onClick={this.addTodo}>登録</button>
                <table className="table mt-5">
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>タスク</th>
                            <th>完了</th>
                        </tr>
                    </thead>
                    <tbody>
                        {/* 行の描画 */}
                        <RenderRows
                            todos={this.state.todos}
                            deleteTask={this.deleteTask}
                        />
                    </tbody>
                </table>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<TodoApp />, document.getElementById('todoApp'));
3
3
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
3
3