Building a Single-Page Application (SPA) with Laravel and React

Creating a blog post about building a single-page application (SPA) using Laravel as the backend and React as the frontend is a great way to share your knowledge. Below is a blog post template that you can use to explain the process step-by-step.


Building a Single-Page Application (SPA) with Laravel and React

In this blog post, we’ll walk through the process of building a single-page application (SPA) using Laravel as the backend and React as the frontend. The application will perform CRUD operations (Create, Read, Update, Delete) on a Post model without requiring a page refresh.


Why Laravel + React?

  • Laravel: A powerful PHP framework for building robust backend APIs.
  • React: A popular JavaScript library for building dynamic and responsive user interfaces.
  • SPA: Single-page applications provide a seamless user experience by eliminating page reloads.

Step 1: Setting Up the Laravel Backend

1. Install Laravel

First, create a new Laravel project:

composer create-project laravel/laravel laravel-react-spa
cd laravel-react-spa

2. Set Up the Database

Update the .env file with your database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_database_user
DB_PASSWORD=your_database_password

3. Create a Model and Migration

Generate a Post model and migration:

php artisan make:model Post -m

Update the migration file (database/migrations/xxxx_xx_xx_create_posts_table.php):

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->timestamps();
    });
}

Run the migration:

php artisan migrate

4. Create an API Controller

Generate a controller for API operations:

php artisan make:controller Api/PostController

Update app/Http/Controllers/Api/PostController.php with CRUD methods:

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    // List all posts
    public function index()
    {
        $posts = Post::all();
        return response()->json($posts);
    }

    // Store a new post
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
        ]);

        $post = Post::create($request->all());
        return response()->json($post, 201);
    }

    // Show a single post
    public function show($id)
    {
        $post = Post::findOrFail($id);
        return response()->json($post);
    }

    // Update a post
    public function update(Request $request, $id)
    {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
        ]);

        $post = Post::findOrFail($id);
        $post->update($request->all());
        return response()->json($post);
    }

    // Delete a post
    public function destroy($id)
    {
        $post = Post::findOrFail($id);
        $post->delete();
        return response()->json(null, 204);
    }
}

5. Define API Routes

Update routes/api.php to define routes manually:

use App\Http\Controllers\Api\PostController;

// List all posts
Route::get('/posts', [PostController::class, 'index']);

// Store a new post
Route::post('/posts', [PostController::class, 'store']);

// Show a single post
Route::get('/posts/{id}', [PostController::class, 'show']);

// Update a post
Route::put('/posts/{id}', [PostController::class, 'update']);

// Delete a post
Route::delete('/posts/{id}', [PostController::class, 'destroy']);

Step 2: Setting Up the React Frontend

1. Install React and Axios

Install React and Axios for API communication:

npm install react react-dom axios
npm install @vitejs/plugin-react --save-dev
npm install

2. Create React Components

Create a folder resources/js/components and add the following files:

PostList.js

This component lists all posts and handles editing and deleting posts.

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import PostItem from './PostItem';
import PostForm from './PostForm';

const PostList = () => {
    const [posts, setPosts] = useState([]);
    const [editingPost, setEditingPost] = useState(null);

    // Fetch all posts
    useEffect(() => {
        fetchPosts();
    }, []);

    const fetchPosts = async () => {
        const response = await axios.get('/api/posts');
        setPosts(response.data);
    };

    // Delete a post
    const deletePost = async (id) => {
        await axios.delete(`/api/posts/${id}`);
        fetchPosts();
    };

    // Edit a post
    const editPost = (post) => {
        setEditingPost(post);
    };

    // Cancel editing
    const cancelEdit = () => {
        setEditingPost(null);
    };

    return (
        <div>
            <h1>Posts</h1>
            <PostForm
                post={editingPost}
                onSave={() => {
                    fetchPosts();
                    cancelEdit();
                }}
            />
            <ul>
                {posts.map((post) => (
                    <PostItem
                        key={post.id}
                        post={post}
                        onDelete={deletePost}
                        onEdit={editPost}
                    />
                ))}
            </ul>
        </div>
    );
};

export default PostList;

PostForm.js

This component handles creating and updating posts.

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const PostForm = ({ post, onSave }) => {
    const [title, setTitle] = useState('');
    const [content, setContent] = useState('');

    // Pre-fill form if editing
    useEffect(() => {
        if (post) {
            setTitle(post.title);
            setContent(post.content);
        }
    }, [post]);

    // Handle form submission
    const handleSubmit = async (e) => {
        e.preventDefault();
        const data = { title, content };

        if (post) {
            await axios.put(`/api/posts/${post.id}`, data);
        } else {
            await axios.post('/api/posts', data);
        }

        onSave();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="Title"
                value={title}
                onChange={(e) => setTitle(e.target.value)}
                required
            />
            <textarea
                placeholder="Content"
                value={content}
                onChange={(e) => setContent(e.target.value)}
                required
            />
            <button type="submit">{post ? 'Update' : 'Create'}</button>
        </form>
    );
};

export default PostForm;

PostItem.js

This component displays a single post with edit and delete options.

import React from 'react';

const PostItem = ({ post, onDelete, onEdit }) => {
    return (
        <li>
            <h2>{post.title}</h2>
            <p>{post.content}</p>
            <button onClick={() => onEdit(post)}>Edit</button>
            <button onClick={() => onDelete(post.id)}>Delete</button>
        </li>
    );
};

export default PostItem;

3. Update app.js

Update resources/js/app.js to render the PostList component:

import React from 'react';
import ReactDOM from 'react-dom/client';
import PostList from './components/PostList';

// Get the root element
const rootElement = document.getElementById('root');

// Create a root and render your component
const root = ReactDOM.createRoot(rootElement);
root.render(<PostList />);

4. Update Blade View

Update resources/views/welcome.blade.php to load the React app:

<!DOCTYPE html>
<html>
<head>
    <title>Laravel React SPA</title>
</head>
<body>
    <div id="root"></div>

     @vite('resources/js/app.jsx') <!-- Include the compiled  --> 
</body>

5. Compile Assets

Compile the React components using Laravel Mix:

npm run dev

Step 3: Testing the Application

  1. Run the Laravel development server:
   php artisan serve
  1. Visit http://localhost:8000 to test the application.

Conclusion

In this blog post, we built a single-page application (SPA) using Laravel as the backend and React as the frontend. The application performs CRUD operations on a Post model without requiring a page refresh. This setup provides a seamless user experience and demonstrates the power of combining Laravel and React.

Feel free to extend this project by adding features like authentication, pagination, or deployment to a live server. Happy coding! 🚀


Let me know if you need further assistance or additional sections for your blog! 😊

Related Post

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x