Using Laravel Constants in React with 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 blog post 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>
</>
);
}
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');
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. Happy coding! 👋