Share Laravel Constants With React via Inertia.js
Consider Reading the Newer Post
This post covers using Laravel constants with React through Inertia.js effectively. However, we've now updated our approach to leverage PHP Enums for greater type safety, maintainability, and cleaner code. If you're looking for a modern alternative, check out the newer post on using Laravel enums in React with Inertia.js that explores these enhancements in depth.
There are many ways to share data between your Laravel backend and your JavaScript frontend. Today, we'll focus on one particularly powerful method: sharing constants between Laravel and JavaScript using Inertia.js. This approach is especially useful for managing dropdowns, form options, or validation rules, ensuring consistency and reducing repetition across your application.
By centralizing constants in Laravel, you create a single source of truth that can be used throughout your backend and frontend. In this post, we'll walk through a practical example of defining platform constants in Laravel and using them seamlessly in a React component.
Why Use Constants?
Constants are essential for maintaining consistency, reducing errors, and improving maintainability. Defining them in Laravel allows you to:
- Share Consistent Data Structures: Share the same data structure between your backend and frontend seamlessly.
- Avoid Duplication: Reduce redundancy and ensure updates propagate across the application effortlessly.
- Simplify Validation and Forms: Make validation rules and dropdown creation in your forms straightforward and error-free.
Step 1: Define the Constants in Laravel
Create a Platform class under app/Constants:
<?php
namespace App\Constants;
class Platform
{
public const PLATFORMS = [
'steam' => 'Steam',
'psn' => 'PlayStation Network',
'xbox' => 'Xbox',
'kakao' => 'Kakao',
'stadia' => 'Stadia',
];
public static function getPlatforms(): array
{
// Transform into a key-value array suitable for frontend use
return collect(self::PLATFORMS)
->map(function ($label, $key) {
return [
'value' => $key,
'label' => $label,
];
})
->values()
->toArray();
}
}
How It Works
In this example, the Platform class defines a centralized list of platforms and formats them.
Using Laravel Collections to Format the Data
The getPlatforms() method in the Platform class leverages Laravel Collections to format the PLATFORMS data into a reusable structure. Let's break down how this works:
Wrap the Data in a Collection
The collect() function takes the PLATFORMS constant and wraps it in a Laravel collection. This allows for easy manipulation of the data.
collect(self::PLATFORMS)
Transform the Data
The map() method iterates over each platform key-value pair and transforms it into an array with the following structure:
value: The platform's key (e.g., steam, psn). label: The platform's human-readable name (e.g., Steam, PlayStation Network).
->map(function ($label, $key) {
return [
'value' => $key,
'label' => $label,
];
})
Flatten the Structure
The values() method resets the array keys to ensure a clean, sequentially indexed array.
->values()
Convert to Plain Array
Finally, the toArray() method converts the collection into a plain PHP array, ready to be passed to the frontend.
->toArray();
What getPlatforms() Produces...
The final output of getPlatforms() is a structured array like this:
[
['value' => 'steam', 'label' => 'Steam'],
['value' => 'psn', 'label' => 'PlayStation Network'],
['value' => 'xbox', 'label' => 'Xbox'],
['value' => 'kakao', 'label' => 'Kakao'],
['value' => 'stadia', 'label' => 'Stadia'],
]
Step 2: Pass the Constants to the Frontend Using Inertia
In your web.php file, pass the platforms to the React component:
use App\Constants\Platform;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Home', [
'platforms' => Platform::getPlatforms(),
]);
})->name('home');
Step 3: Use the Constants in Your React Component
In this step, we make use of the usePage hook provided by Inertia.js to access the constants passed from Laravel. The usePage hook is a powerful utility that allows you to directly access the page's props in your React component. These props are passed down from your Laravel backend via Inertia when rendering the page.
For more details, check out the official documentation on shared data with Inertia.
Here's how usePage is useful in this scenario:
• Seamless Data Sharing:
The usePage hook enables seamless sharing of data between the backend and frontend without the need for additional API calls. In our case, the platforms constant is passed as a prop from Laravel, and we access it directly in the React component using usePage.
• Centralized State Management:
Since usePage provides access to all props sent with the current Inertia response, it serves as a centralized way to manage and access state or configuration data required for a specific page.
• Dynamic and Flexible:
With usePage, any data passed from Laravel, such as the platforms list, is dynamically available in the React component. This flexibility ensures that updates to the backend logic (e.g., enabling/disabling platforms) are automatically reflected in the frontend.
import React from "react";
import { Head, useForm, usePage } from "@inertiajs/react";
export default function Home() {
// Access platforms from the page props
const { platforms } = usePage().props;
// Form state using Inertia's useForm hook
const { data, setData, post, processing, errors } = useForm({
username: "", // Input for the username
platform: platforms?.[0]?.value || "steam", // Default to the first platform
});
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
post(route("search"));
};
return (
<>
<Head title="Platform Selector" />
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<div className="w-full max-w-md bg-white shadow rounded p-6">
<h1 className="text-2xl font-bold mb-4">Select Your Platform</h1>
<form onSubmit={handleSubmit}>
{/* Platform Dropdown */}
<select
className="w-full p-2 border border-gray-300 rounded mb-4"
value={data.platform}
onChange={(e) => setData("platform", e.target.value)}
>
{platforms.map((platform) => (
<option key={platform.value} value={platform.value}>
{platform.label}
</option>
))}
</select>
{errors.platform && (
<div className="text-red-500 text-sm">{errors.platform}</div>
)}
{/* Username Input */}
<input
type="text"
placeholder="Enter Username"
className="w-full p-2 border border-gray-300 rounded mb-4"
value={data.username}
onChange={(e) => setData("username", e.target.value)}
/>
{errors.username && (
<div className="text-red-500 text-sm">{errors.username}</div>
)}
{/* Submit Button */}
<button
type="submit"
className="w-full bg-blue-500 text-white p-2 rounded"
disabled={processing}
>
{processing ? "Submitting..." : "Submit"}
</button>
</form>
</div>
</div>
</>
);
}
Note on
route(): Theroute("search")helper used above is not built into Inertia or React. It comes from Ziggy, which exposes your Laravel named routes to JavaScript. If you are not using Ziggy, swap it for the plain path instead, for examplepost("/search").
Step 4: Reuse Constants Anywhere
Want to use these platforms elsewhere, like in validation? The Platform constant is ready to go:
use App\Constants\Platform;
use Illuminate\Http\Request;
Route::post('/search', function (Request $request) {
$request->validate([
'username' => 'required|string|max:255',
'platform' => 'required|in:' . implode(',', array_keys(Platform::PLATFORMS)),
]);
// Handle the search logic here
return response()->json(['message' => 'Search successful']);
})->name('search');
On modern Laravel you can express the allow-list with the fluent Rule::in() builder instead of string concatenation, which reads more clearly and is easier to extend:
use App\Constants\Platform;
use Illuminate\Validation\Rule;
$request->validate([
'username' => 'required|string|max:255',
'platform' => ['required', Rule::in(array_keys(Platform::PLATFORMS))],
]);
Both forms read from the same Platform::PLATFORMS constant, so the dropdown the user sees and the values the backend accepts can never drift apart.
Conclusion
By centralizing your constants in Laravel and using Inertia.js, you can easily share data between your backend and frontend:
- Write Once: Define your constants in Laravel.
- Reuse Everywhere: Use them in React, validation, or other backend logic.
- Keep it Simple: Laravel and Inertia make the data flow seamless.
This approach ensures consistency and makes your codebase easier to maintain.
Frequently Asked Questions
How do I pass Laravel data to a React component with Inertia.js?
Return the data as a prop from your route or controller via Inertia::render('Page', ['key' => $value]). In the React component, read it with the usePage hook: const { key } = usePage().props. No separate API call or fetch is needed because Inertia serializes the props into the initial page response.
Should I use PHP constants or enums to share data with React?
Class constants are the simplest option and work on any PHP version. PHP 8.1 enums are the better choice for new code because they add type safety, can hold behaviour as methods, and prevent invalid values at the type level. If you are on PHP 8.1 or later, prefer enums. See the follow-up post on using Laravel enums in React with Inertia.js for the upgraded version of this exact example.
How do I reuse the same options for backend validation?
Because the values live in a PHP constant, you can reference them directly in a validation rule. For an allow-list use Rule::in(array_keys(Platform::PLATFORMS)) or the string form 'in:' . implode(',', array_keys(Platform::PLATFORMS)). The frontend dropdown and the backend validation then read from the same source, so they can never drift apart.
Related Reading
- Using Laravel Enums in React with Inertia.js: A Modern Update - the type-safe successor to this approach using PHP 8.1 enums.
- How to Add a Dark Mode Toggle in Tailwind CSS (Alpine.js) - another single-source-of-truth pattern, applied to theme state instead of data.
Happy coding!