viernes, 11 de julio de 2025

Manejo de Inertia de las redirecciones desde un controlador

 ¿Cuál sería el equivalente en Inertia del siguiente código de controlador?


return redirect('/login')->withErrors(['social' => 'No se pudo autenticar con ' . ucfirst($provider) . '. Por favor, inténtalo de nuevo.']);


Es un punto clave para entender cómo Inertia maneja las redirecciones y los mensajes de sesión.

En Inertia.js, la forma de manejar una redirección con mensajes (como errores o flashes) es muy similar a cómo lo harías en Laravel tradicional, porque Inertia está diseñado para interceptar esas redirecciones.

El equivalente de Inertia para:

PHP
return redirect('/login')->withErrors(['social' => 'No se pudo autenticar con ' . ucfirst($provider) . '. Por favor, inténtalo de nuevo.']);

Sería exactamente el mismo código en tu controlador de Laravel.


¿Por qué es el mismo código?

La magia de Inertia.js es que intercepta las respuestas de redirección HTTP que Laravel envía.

  1. Cuando tu controlador Laravel ejecuta return redirect('/login')->withErrors([...]);, Laravel genera una respuesta HTTP 302 (redirección) con los errores en la sesión.

  2. Inertia en el frontend detecta esta redirección. En lugar de que el navegador realice una recarga completa de la página (lo que pasaría sin Inertia), Inertia realiza una visita XHR (AJAX) a la URL de destino (/login).

  3. Cuando Inertia recibe la respuesta de /login (que es otra página Inertia o una vista Blade, dependiendo de tu configuración), también recupera los errores de la sesión flash que Laravel adjuntó.

  4. Estos errores se hacen disponibles en el frontend de React (o Vue/Svelte) a través del hook usePage().props.errors.


Ejemplo Completo (Controlador Laravel y Componente React)

Aquí te muestro cómo se vería en el controlador y cómo lo recibirías en tu componente de React:

Controlador de Laravel (Backend)
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Auth;
use App\Models\User; // Asegúrate de importar tu modelo User

class SocialiteController extends Controller
{
// ... (método redirectToProvider)

public function handleProviderCallback(string $provider)
{
try {
$socialUser = Socialite::driver($provider)->user();
} catch (\Exception $e) {
// ¡Aquí es donde usarías el código!
return redirect('/login')->withErrors([
'social' => 'No se pudo autenticar con ' . ucfirst($provider) . '. Por favor, inténtalo de nuevo.'
]);
}

// Lógica para buscar o crear el usuario...
$user = User::where('provider', $provider)
->where('provider_id', $socialUser->getId())
->first();

if ($user) {
Auth::login($user);
return redirect('/dashboard');
} else {
$newUser = User::create([
'name' => $socialUser->getName() ?? $socialUser->getNickname() ?? 'Usuario Social',
'email' => $socialUser->getEmail(),
'password' => null,
'provider' => $provider,
'provider_id' => $socialUser->getId(),
]);
Auth::login($newUser);
return redirect('/dashboard');
}
}
}



Componente de React (Frontend)
// resources/js/Pages/Auth/Login.jsx (o donde tengas tu formulario de login)

import React from 'react';
import { Head, usePage, Link } from '@inertiajs/react';
import GuestLayout from '@/Layouts/GuestLayout'; // Tu layout base para invitados

export default function Login({ status }) {
// El hook usePage() te da acceso a los props de la página, incluyendo los errores.
const { errors } = usePage().props;

// Aquí puedes acceder a los errores específicos:
const socialError = errors.social;

return (
<GuestLayout>
<Head title="Iniciar Sesión" />

{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}

{/* Formulario de Login tradicional (omito detalles por brevedad) */}
<form>
{/* ... campos de email y contraseña ... */}
<button type="submit">Iniciar Sesión</button>
</form>

<hr className="my-6" />

<div className="text-center">
<p className="mb-4">O inicia sesión con:</p>
{/* Botones de Socialite */}
<a href={route('socialite.redirect', { provider: 'google' })} className="inline-block px-4 py-2 border rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50">
Google
</a>
<a href={route('socialite.redirect', { provider: 'github' })} className="inline-block px-4 py-2 border rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 ml-4">
GitHub
</a>
</div>

{/* Mostrar el error de Socialite si existe */}
{socialError && (
<div className="text-red-500 text-sm mt-4 text-center">
{socialError}
</div>
)}

{/* También puedes mostrar todos los errores de validación si los hubiera */}
{Object.keys(errors).length > 0 && !socialError && (
<div className="text-red-500 text-sm mt-4 text-center">
Hubo un error al procesar tu solicitud.
</div>
)}
</GuestLayout>
);
}

Puntos Clave:

  • Mismo Código Backend: No cambias la forma en que Laravel maneja las redirecciones o los mensajes flash.

  • Inertia lo Intercepta: Inertia se encarga de la "magia" de convertir esa redirección HTTP en una navegación de SPA.

  • usePage().props.errors: Este es el mecanismo en el frontend de React para acceder a los errores de validación o mensajes flash que Laravel haya puesto en la sesión y enviado con la respuesta de Inertia.

Esta es una de las grandes ventajas de Inertia: te permite mantener gran parte de tu lógica de Laravel intacta, incluso para la gestión de respuestas HTTP que tradicionalmente implicarían recargas de página.

No hay comentarios: