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
- Run the Laravel development server:
php artisan serve
- 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! 😊