React, The Laravel Way
In "React from Scratch", we built a "DevPups" app from scratch. Now it's time to take things further. Using that finished app as a base, you'll learn how to construct a React-powered app...the Laravel way!
You'll see how we can swap out fragile external API calls for Laravel's elegant backend, add real-time "like" functionality, support file uploads, and polish up our CRUD features with proper authorization. Along the way, you'll get comfortable with Inertia.js, the perfect glue between Laravel's backend strength and React's frontend flexibility.
By the end of this series, you'll have constructed a production-ready app that shows the Laravel way of working with React: fewer moving parts, cleaner architecture, and faster development.
Progress
Series Info
- Episodes
- 30
- Run Time
- 6h 25m
- Difficulty
- Intermediate
- Last Updated
- Sep 17, 2025
- Version
- Latest
Series Episodes
- From Vanilla React to Laravel Integration (8)
Introduction
In this kickoff, we take the React "DevPups" app from the React from Scratch series and set the stage for porting it to Laravel + Inertia + React. We'll talk about where vanilla React falls short—things like data fetching, invalidation, authentication, and routing—and how Laravel plus Inertia step in to fill those gaps.Vanilla App Port
We start with the existing DevPups app and spin up a fresh Laravel project using the React starter kit. Together, we'll review the original app's structure, dependencies, and API calls, then begin migrating those pieces into our new Laravel + Inertia setup. Authentication scaffolding is included out of the box, which gives us a strong foundation.In-House Puppy Data
Instead of reaching for an external API, we'll bring our puppy data in-house. That means setting up a model, migration, and seeder in Laravel so the data lives right inside our app. The result: simpler React components without spinners, retries, or error boundaries—Inertia handles the server-to-client flow for us.Images In Public & Local Driver
Time to organize our puppy images. We'll move them out of the public directory and into Laravel's storage system, hook them up with Storage::url(), and create the symlink with php artisan storage:link. This keeps things tidy and prepares us for future file uploads.JSON Resources
Rather than dumping raw model data into the frontend, we'll clean it up with Laravel's JSON Resources. We'll shape the data, expose only what we need, and format fields in camelCase for React. We'll also globally disable resource wrapping for cleaner integration with Inertia.Liked Puppies Relationship
Let's wire up the database for "liking" puppies. We'll create a pivot table with proper foreign keys, cascade deletes, and uniqueness rules so users can like multiple puppies (and puppies can be liked by multiple users) without messy duplicates.Real Puppies In The Front End
With our data now living in Laravel, we can remove all the complexity of async React fetching. No more suspense boundaries, spinners, or custom error states. Inertia does the heavy lifting, leaving our React components far simpler and easier to reason about.User Accounts And Login UI
We'll take advantage of the starter kit's authentication system. After a quick tweak to redirect users to the homepage, we'll review the controllers and set up the login/logout UI so users can actually interact with the system.
- Interactive Features & State Management (7)
Like Toggle Refactoring
Here we'll make the "like" heart button instant and reliable. We'll build proper routes and controllers in Laravel, keep endpoints idempotent, and let Inertia handle syncing the database with the UI for smooth, real-time feedback.Pending State UI
A small touch that makes a big difference: pending states. We'll disable buttons, provide subtle visual feedback, and ensure users always know when an action is in progress. Good UX is all about removing uncertainty.Processing State From The useForm Helper
Instead of hand-rolling form state logic, we'll lean on Inertia's useForm hook. It automatically tracks pending states, handles validation errors, resets forms, and more—saving us from boilerplate and keeping our components clean.Server Side Search Filtering
We'll push search logic to the backend where it belongs. Using Laravel's query builder, we'll filter puppies by name and traits, pass parameters through Inertia, and let the server handle the heavy lifting. The UI stays fast and responsive without bloating the client.Filter Search Performance
Search features tend to grow. To keep things snappy, we'll add indexes, eager load relationships, and refine our queries to avoid N+1 problems. These small optimizations ensure performance holds up as data scales.Pagination
Large lists? No problem. We'll use Laravel's paginator, customize the links, and pipe everything through Inertia. Filters and search terms carry across pages, giving users a smooth paginated experience.Inertia Forms
Another step deeper into Inertia's form helpers. Beyond pending states, we'll cover automatic error handling, resets, and success redirects. The end result: less manual code and more reliable forms.
- File Uploads (5)
Image Uploads
Let's add file uploads for puppy photos. We'll configure Laravel to validate and store images, then wire up React to preview the photo before submission. A smooth and user-friendly flow from start to finish.Persisting New Puppies
Time to connect the form all the way to the database. We'll validate, store the image, save the record, and let Inertia refresh the UI so new puppies show up instantly without extra state wrangling.Puppy Creation Form Polish
Little details matter. We'll reset fields after submission, manage focus properly, and add a few subtle touches that make the form feel polished and professional.Image Optimization
Raw uploads are often too big. We'll use Laravel's image processing libraries to resize, compress, and optimize puppy photos automatically—speeding up load times without sacrificing quality.Reusable Image Optimization Action
Rather than duplicating image logic everywhere, we'll encapsulate it in a reusable Laravel Action class. This keeps code clean, testable, and consistent across the app.
- Polish & UX Enhancement (4)
Fixing The Shortlist Bug
Bugs happen. Here, we'll debug a state mismatch in the shortlist feature by tracing the flow between server and client. Once fixed, we'll add guardrails to prevent similar issues in the future.Reset Pagination On Create
Without care, newly created puppies can end up "hidden" on later pages. We'll reset pagination automatically so users always see what they just added.Command To Delete Unused Images
Over time, orphaned image files build up. We'll create a custom Artisan command that reconciles storage with the database and safely cleans up unused files.Toast Notifications
To keep users informed without being intrusive, we'll build toast notifications for successes, errors, and status messages. It's a small feature that makes the app feel alive and responsive.
- CRUD Operations (6)
Delete Action
Deleting records deserves special care. We'll add confirmation dialogs, enforce backend authorization, and make sure the UI updates instantly after deletion— all while keeping destructive actions safe.Authorization Policy
Not everyone should be able to edit or delete everything. We'll use Laravel's Policy classes to lock down puppy updates/deletes to the rightful owners, and pass that state to React for conditional UI rendering.Dialog Pending State
Async actions inside dialogs can feel awkward. We'll improve them with loading indicators, disabled buttons, and consistent pending states—helping users trust that something is happening.Update Action Frontend
We'll build edit forms that load existing puppy data, validate submissions, and update records with Inertia. Errors are handled gracefully, and the flow feels seamless for the user.PUT Method Spoofing
Since HTML forms only support GET and POST, we'll use Laravel's method spoofing to respect RESTful verbs like PUT, PATCH, and DELETE. This keeps our routes semantic while still working with Inertia forms.Image Upload Preview
Finally, we'll add live previews for image uploads. Users see their chosen photo immediately, while we handle cleanup behind the scenes to avoid memory leaks. A small but satisfying feature.
