Skip to content

All topics  /  Laravel

Laravel 9 React CRUD Example Tutorial

Laravel ·

Teams applying “Laravel 9 React CRUD Example Tutorial” in a production project can use in house recruiter to record implementation, review and debugging time, then compare that effort with tests and shipped functionality instead of treating activity as performance by itself.

Before copying the example into a live application, confirm version-specific behaviour with the official Laravel website and test it against the project’s actual database and runtime.

Hello Friends,

This tutorial will show you how to generate react crud in Laravel using examples. We will assist you by providing examples of how to build react code in the tutorial for laravel. This article will provide a straightforward example of how to develop React.js code using the Laravel framework. It's an easy example of how to use Laravel with React.js to create a simple, crude app. Just follow a few simple instructions to learn how to create a basic app using Laravel and React.

laravel react js crud example; Through this tutorial, we will learn how to make react crud with laravel apps.

Now let's start.

Step 1: Install Laravel Application


This is optional; however, if you have not created the laravel app, then you may go ahead and execute the below command:

composer create-project laravel/laravel example-app

Step 2: Database Configuration

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=here your database name(blog)
DB_USERNAME=here database username(root)
DB_PASSWORD=here database password(root)    

Step 3: Create Auth with Breeze

To create auth with breeze in Laravel apps, then run the command line following:

composer require laravel/breeze --dev
php artisan breeze:install react
npm install
npm run dev     

Step 4: Create Migration and Model

php artisan make:migration create_posts_table    

Then update migration file by using the following code:

database/migrations/create_posts_table.php

<?php

  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

  
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }

  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}    

And to create a Post.php model, use the following command on the command line:

php artisan make:model Post    

App/Models/Post.php

<?php

  
namespace App\Models;

  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

  
class Post extends Model
{
    use HasFactory;

  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title', 'body'
    ];
}    

And then, execute the following command on command line to create tables into database:

php artisan migrate    

Step 5: Create Routes

routes/web.php

<?php

 
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use App\Http\Controllers\PostController;

  
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

   
Route::resource('posts', PostController::class);

   
Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});

    
Route::get('/dashboard', function () {
    return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

   
require __DIR__.'/auth.php';    

Step 6: Create Controller

php artisan make:controller PostController    

app/Http/Controllers/PostController.php.

<?php

   
namespace App\Http\Controllers;

    
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\Post;
use Illuminate\Support\Facades\Validator;

   
class PostController extends Controller
{
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function index()
    {
        $posts = Post::all();
        return Inertia::render('Posts/Index', ['posts' => $posts]);
    }

  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function create()
    {
        return Inertia::render('Posts/Create');
    }

    
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function store(Request $request)
    {
        Validator::make($request->all(), [
            'title' => ['required'],
            'body' => ['required'],
        ])->validate();

   
        Post::create($request->all());

    
        return redirect()->route('posts.index');
    }

  
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function edit(Post $post)
    {
        return Inertia::render('Posts/Edit', [
            'post' => $post
        ]);
    }

    
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function update($id, Request $request)
    {
        Validator::make($request->all(), [
            'title' => ['required'],
            'body' => ['required'],
        ])->validate();

    
        Post::find($id)->update($request->all());
        return redirect()->route('posts.index');
    }

    
    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function destroy($id)
    {
        Post::find($id)->delete();
        return redirect()->route('posts.index');
    }
}    

Step 7: Create Views

Index.jsx, Create.jsx, and Edit.jsx should be created as react js files.

resources/js/Pages/Posts/index.jsx

import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Inertia } from "@inertiajs/inertia";
import { Head, usePage, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
    const { posts } = usePage().props

    
    function destroy(e) {
        if (confirm("Are you sure you want to delete this user?")) {
            Inertia.delete(route("posts.destroy", e.currentTarget.id));
        }
    }
    return (
            <Authenticated auth={props.auth} errors={props.errors} header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Posts</h2>}>       
                <Head title="Posts" />
                <div className="py-12">
                    <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
                        <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                            <div className="p-6 bg-white border-b border-gray-200">
                                <div className="flex items-center justify-between mb-6">
                                    <Link className="px-6 py-2 text-white bg-green-500 rounded-md focus:outline-none" href={ route("posts.create") }>Create Post</Link>
                                </div>
                                <table className="table-fixed w-full">
                                    <thead>
                                        <tr className="bg-gray-100">
                                            <th className="px-4 py-2 w-20">No.</th>
                                            <th className="px-4 py-2">Title</th>
                                            <th className="px-4 py-2">Body</th>
                                            <th className="px-4 py-2">Action</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {posts.map(({ id, title, body }) => (
                                            <tr>
                                                <td className="border px-4 py-2">{ id }</td>
                                                <td className="border px-4 py-2">{ title }</td>
                                                <td className="border px-4 py-2">{ body }</td>
                                                <td className="border px-4 py-2">
                                                    <Link tabIndex="1" className="px-4 py-2 text-sm text-white bg-blue-500 rounded" href={route("posts.edit", id)} >Edit</Link>
                                                    <button onClick={destroy} id={id} tabIndex="-1" type="button" className="mx-1 px-4 py-2 text-sm text-white bg-red-500 rounded" >Delete</button>
                                                </td>
                                            </tr>
                                        ))}
                                        {posts.length === 0 && (
                                            <tr>
                                                <td className="px-6 py-4 border-t"colSpan="4">No contacts found.</td>
                                            </tr>
                                        )}
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </Authenticated>
        );
    }    

resources/js/Pages/Posts/create.jsx

import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Head, useForm, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
    const { data, setData, errors, post } = useForm({
        title: "",
        description: "",
    });
    function handleSubmit(e) {
        e.preventDefault();
        post(route("posts.store"));
    }
    return (
        <Authenticated auth={props.auth} errors={props.errors} header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Create Post</h2>}>
            <Head title="Posts" />
            <div className="py-12">
                <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
                    <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                        <div className="p-6 bg-white border-b border-gray-200">
                            <div className="flex items-center justify-between mb-6">
                                <Link className="px-6 py-2 text-white bg-blue-500 rounded-md focus:outline-none" href={ route("posts.index") }>Back</Link>
                            </div>
                            <form name="createForm" onSubmit={handleSubmit}>
                                <div className="flex flex-col">
                                    <div className="mb-4">
                                        <label className="">Title</label>
                                        <input type="text" className="w-full px-4 py-2" label="Title" name="title" value={data.title} onChange={(e) => setData("title", e.target.value) }/>
                                        <span className="text-red-600">
                                            {errors.title}
                                        </span>
                                    </div>
                                    <div className="mb-0">
                                        <label className="">Body</label>
                                        <textarea type="text" className="w-full rounded" label="body" name="body" errors={errors.body} value={data.body} onChange={(e) => setData("body", e.target.value) }/>
                                        <span className="text-red-600">
                                            {errors.body}
                                        </span>
                                    </div>
                                </div>
                                <div className="mt-4">
                                    <button type="submit" className="px-6 py-2 font-bold text-white bg-green-500 rounded">Save</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </Authenticated>
    );
}    

resources/js/Pages/Posts/edit.jsx

import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Head, useForm, usePage, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
    const { post } = usePage().props;
    const { data, setData, put, errors } = useForm({
        title: post.title || "",
        body: post.body || "",
    });
    function handleSubmit(e) {
        e.preventDefault();
        put(route("posts.update", post.id));
    }
    return (
        <Authenticated auth={props.auth} errors={props.errors} header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Edit Post</h2>}>
            <Head title="Posts" />
            <div className="py-12">
                <div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
                    <div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                        <div className="p-6 bg-white border-b border-gray-200">
                            <div className="flex items-center justify-between mb-6">
                                <Link className="px-6 py-2 text-white bg-blue-500 rounded-md focus:outline-none" href={ route("posts.index") }>Back</Link>
                            </div>
                            <form name="createForm" onSubmit={handleSubmit}>
                                <div className="flex flex-col">
                                    <div className="mb-4">
                                        <label className="">Title</label>
                                        <input type="text" className="w-full px-4 py-2" label="Title" name="title" value={data.title} onChange={(e) => setData("title", e.target.value) }/>
                                        <span className="text-red-600">
                                            {errors.title}
                                        </span>
                                    </div>
                                    <div className="mb-0">
                                        <label className="">Body</label>
                                        <textarea type="text" className="w-full rounded" label="body" name="body" errors={errors.body} value={data.body} onChange={(e) => setData("body", e.target.value) }/>
                                        <span className="text-red-600">
                                        {errors.body}
                                        </span>
                                    </div>
                                </div>
                                <div className="mt-4">
                                    <button type="submit" className="px-6 py-2 font-bold text-white bg-green-500 rounded">Update</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </Authenticated>
    );
}    

Now add posts module link on header navbar. Then update add following line on Authenticated.jsx file:

Authenticated.jsx

...
<NavLink href={route('posts.index')} active={route().current('posts.index')}>
    Posts
</NavLink>
...    

Step 8: Start Development Server execute the following command on command line to start development server:

php artisan serve    

run the following command for vite:

npm run dev    

If we want to build then you can run following command:

npm run build    

Now, Go to web browser, type the following URL:

http://localhost:8000