Help us understand the problem. What is going on with this article?

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

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'));
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away