Using Laravel Enums in React with Inertia.js: A Modern Update
When building modern web applications, ensuring consistent data structures between your backend and frontend is essential. In a previous post, I demonstrated how Laravel constants could be used to share data seamlessly with React through Inertia.js. However, with the introduction of PHP 8.1 Enums (further enhanced in PHP 8.3), I’ve refined my approach to fully leverage this powerful feature.
Enums offer type safety, cleaner syntax, and encapsulated behavior that surpasses the simplicity of constants. In this updated post, I’ll walk you through the benefits of using enums, how to implement them in Laravel, and why they’re a better alternative to constants for most use cases.
Why Share Data Between Laravel and React?
Sharing data like dropdown options, validation rules, and configuration values between the backend and frontend ensures:
- Consistency: Both layers use the same source of truth, reducing discrepancies.
- Maintainability: Updates to shared data propagate seamlessly across the application.
- Developer Productivity: Eliminates redundant code and reduces errors.
Traditionally, constants were the go-to solution for this, but enums now provide an improved alternative.
What Are Enums and How Are They Different from Constants?
Constants
Constants are static values defined in a class or file. They’re simple, lightweight, and great for defining unchanging data. For example:
class Platform
{
public const PLATFORMS = [
'steam' => 'Steam',
'psn' => 'PlayStation Network',
'xbox' => 'Xbox',
'kakao' => 'Kakao',
'stadia' => 'Stadia',
];
}
Limitations:
No type safety: You need custom validation to ensure only valid keys are used.
Static behavior: You can’t add methods or encapsulate related logic.
Enums:
Enums are a newer feature in PHP that represent a finite set of values with built-in type safety and encapsulated logic. Example:
enum PlatformEnum: string
{
case Steam = 'steam';
case PlayStationNetwork = 'psn';
case Xbox = 'xbox';
case Kakao = 'kakao';
case Stadia = 'stadia';
}
Advantages:
Type Safety: Only defined enum cases are allowed.
Encapsulated Behavior: Enums can include methods for transformations or additional data.
Cleaner Code: Eliminates boilerplate and reduces the risk of errors.
Why I Switched to Enums
Here are the key reasons I moved from constants to enums:
Type Safety: With enums, you can ensure only valid values are used throughout your application:
$request->validate([
'platform' => 'required|in:' . implode(',', PlatformEnum::values()),
]);
This reduces the risk of errors caused by typos or outdated constants.
Centralized Behavior: Enums allow you to group related logic in one place. For example, you can define dropdown options directly in the enum:
public static function options(): array
{
return array_map(
fn($case) => ['value' => $case->value, 'label' => self::labels()[$case->value]],
self::cases()
);
}
Better Validation: With enums, validation is more robust and concise, as enum values are inherently valid.
Future-Proofing: Adding new platforms or modifying behavior is easier with enums. Constants often require updating multiple locations.
Cleaner Syntax: Enums reduce boilerplate code by combining data and behavior in a single structure.
Implementing Laravel Enums
Here’s how I updated my application to use enums instead of constants:
Step 1: Define the Enum
Create the PlatformEnum under app/Enums:
<?php
namespace App\Enums;
enum PlatformEnum: string
{
case Steam = 'steam';
case PlayStationNetwork = 'psn';
case Xbox = 'xbox';
case Kakao = 'kakao';
case Stadia = 'stadia';
public static function labels(): array
{
return [
self::Steam->value => 'Steam',
self::PlayStationNetwork->value => 'PlayStation Network',
self::Xbox->value => 'Xbox',
self::Kakao->value => 'Kakao',
self::Stadia->value => 'Stadia',
];
}
public static function options(): array
{
return array_map(
fn($case) => ['value' => $case->value, 'label' => self::labels()[$case->value]],
self::cases()
);
}
public static function values(): array
{
return array_map(fn($case) => $case->value, self::cases());
}
}
Step 2: Share Data with React Using Inertia
In your web.php file, pass the enum data to your React component:
use App\Enums\PlatformEnum;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Home', [
'platforms' => PlatformEnum::options(),
]);
});
Step 3: Use Enums in React
Access the platforms prop in your React component and generate the dropdown options:
const { platforms } = usePage().props;
<select>
{platforms.map(({ value, label }) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
Step 4: Validation Made Easy
Enums simplify validation by providing a definitive list of valid values:
$request->validate([
'platform' => 'required|in:' . implode(',', PlatformEnum::values()),
]);
When to Use Constants Instead
While enums are ideal for structured, finite sets of values, constants still have their place:
- For Static Data: If the values won’t change and don’t require additional behavior.
- For Simplicity: In cases where you don’t need the added functionality of enums.
- For Backward Compatibility: If your project needs to support PHP versions before 8.1.
Conclusion
By switching from constants to enums, I’ve made my application:
- More Type-Safe: Reducing errors caused by invalid data.
Easier to Maintain: Centralizing logic and behavior within enums. - Cleaner: Streamlining validation and frontend integration.
If you’re using PHP 8.1 or later, enums are a fantastic way to modernize your codebase. If you’re stuck on older versions, constants remain a reliable option. This transition reflects my journey as a developer and my commitment to improving both my code and my learning process.
Let me know your thoughts or share your experience with enums!