Como criar formulário de cadastro com Laravel 11 e React
Neste tutorial, será apresentado como criar um formulário de cadastro com Laravel 11 + Breeze + React.
Primeiramente, será demonstrado como criar o formulário com React.
Em seguida, será explicado como receber os dados do formulário com Laravel.
Por fim, será mostrado como realizar o cadastro no banco de dados com Laravel.
Download do código fonte desenvolvido na aula: Download
PlayList sobre Laravel 11 + Breeze + React 11: Acessar
Receber as aulas gratuitas do curso de Laravel: Acessar
Para começar, é utilizado como base o projeto da aula "Como criar a página visualizar com Laravel 11 e React".
Criada a rota no arquivo "routes/web.php".
Route::get('/create-user', [UserController::class, 'create'])->name('users.create');
Criado o método "create" na controller "app/Http/Controllers/UserController.php". O método é responsável por carregar a "view Users/UserCreate.jsx".
public function create(): Response
{
return Inertia::render('Users/UserCreate');
}
Criada a view com React no Laravel, em "resources/js/Pages/Users/UserCreate.js", com o formulário e a função handleSubmit, que recebe os dados do formulário.
import PrimaryButton from '@/Components/Button/PrimaryButton';
import SuccessButton from '@/Components/Button/SuccessButton';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import { Head, Link, useForm } from '@inertiajs/react';
export default function UserCreate({ auth, user }) {
const {data, setData, post, processing, errors} = useForm({
name: '',
email: '',
password: '',
password_confirmation: '',
});
const handleSubmit = (e) => {
e.preventDefault(); // Não atualizar a página
// Enviar os dados para a rota cadastrar
post(route('users.store'));
}
return (
<AuthenticatedLayout
user={auth.user}
header={<h2 className="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Usuário</h2>}
>
<Head title="Usuário" />
<div className="py-4 max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="overflow-hidden bg-white shadow-lg sm:rounded-lg dark:bg-gray-800">
<div className="flex justify-between items-center m-4">
<h3 className="text-lg">Cadastrar</h3>
<div className="flex space-x-4">
<Link href={route('users.index')}>
<PrimaryButton className="text-sm">Listar</PrimaryButton>
</Link>
</div>
</div>
{/* Formulário para cadastar usuário */}
<div className="bg-gray-50 text-sm dark:bg-gray-700 p-4 rounded-lg shadow-md">
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label htmlFor="name" className="block text-sm font-medium text-gray-700 ">Nome</label>
<input
id="name"
type="text"
placeholder="Nome completo do usuário"
value={data.name}
onChange={(e) => setData('name', e.target.value)}
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
{errors.name && <span className="text-red-600">{errors.name}</span>}
</div>
<div className="mb-4">
<label htmlFor="email" className="block text-sm font-medium text-gray-700 ">E-mail</label>
<input
id="email"
type="email"
placeholder="Melhor e-mail do usuário"
value={data.email}
onChange={(e) => setData('email', e.target.value)}
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
{errors.email && <span className="text-red-600">{errors.email}</span>}
</div>
<div className="mb-4">
<label htmlFor="password" className="block text-sm font-medium text-gray-700 ">Senha</label>
<input
id="password"
type="password"
autoComplete="password"
value={data.password}
onChange={(e) => setData('password', e.target.value)}
placeholder="Senha para o usuário acessar o sistema"
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
{errors.password && <span className="text-red-600">{errors.password}</span>}
</div>
<div className="mb-4">
<label htmlFor="password_confirmation" className="block text-sm font-medium text-gray-700 ">Confirmar a Senha</label>
<input
id="password_confirmation"
type="password"
autoComplete="password_confirmation"
placeholder="Confirmar a senha"
value={data.password_confirmation}
onChange={(e) => setData('password_confirmation', e.target.value)}
className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
{errors.password_confirmation && <span className="text-red-600">{errors.password_confirmation}</span>}
</div>
<div className="flex justify-end">
<SuccessButton
type="submit"
disabled={processing}
className="text-sm"
>
Cadastrar
</SuccessButton>
</div>
</form>
</div>
</div>
</div>
</AuthenticatedLayout>
);
}
Os dados do formulário acima são enviados para a rota "users.store", sendo necessário criá-la no arquivo "routes/web.php".
Route::post('/store-user', [UserController::class, 'store'])->name('users.store');
Criado o método "store" na controller "app/Http/Controllers/UserController.php". O método é responsável por cadastrar o usuário no banco de dados e redirecionar para a tela de visualização "users.show".
public function store(Request $request)
{
// Validar os dados de formulário
$request->validate(
[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|max:255|confirmed',
],
[
'name.required' => 'O campo nome é obrigatório.',
'name.string' => 'O nome deve ser uma string válida.',
'name.max' => 'O nome não pode ter mais que 255 caracteres.',
'email.required' => 'O campo e-mail é obrigatório.',
'email.string' => 'O e-mail deve ser uma string válida.',
'email.email' => 'O e-mail deve ser um endereço de e-mail válido.',
'email.max' => 'O e-mail não pode ter mais que 255 caracteres.',
'email.unique' => 'Este e-mail já está cadastrado.',
'password.required' => 'O campo senha é obrigatório.',
'password.string' => 'A senha deve ser uma string válida.',
'password.min' => 'A senha deve ter no mínimo 8 caracteres.',
'password.confirmed' => 'A confirmação da senha não corresponde.',
]
);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => $request->password,
]);
return Redirect::route('users.show', ['user' => $user->id])->with('success', 'Usuário cadastrado com sucesso!');
}
Para receber a mensagem de sucesso salva na sessão success, é necessário acrescentar o flash no middleware "app/Http/Middleware/HandleInertiaRequests.php".
return [
...parent::share($request),
'auth' => [
'user' => $request->user(),
],
'flash' => [
'success' => fn () => $request->session()->get('success')
],
];
Na página de visualização, ou seja, na view "resources/js/Pages/Users/UserShow.js", é necessário receber a mensagem que está em props.
import { Head, Link, usePage } from '@inertiajs/react';
const {flash} = usePage().props;
Para finalizar, a mensagem de sucesso é impressa.
{flash.success && (<div className="p-3 m-3 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400">{flash.success}</div>)}
Baixar o código-fonte completo do projeto.
Bom, era isso. Espero que o tutorial tenha sido útil!