> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduzione a React — le basi per usarlo con Inertia × Laravel

> Guida introduttiva all'uso di React con Laravel + Inertia.js. Ripercorre la storia da laravel/ui allo starter kit attuale e spiega in modo pratico gli hook React di Inertia come useForm e usePage.

## Cos'è React

React è una libreria JavaScript per costruire interfacce utente, sviluppata e mantenuta da Meta (ex Facebook). È caratterizzata da una descrizione dichiarativa della UI e da un'architettura **basata sui componenti**, e viene usata da piccoli widget a intere SPA.

Il cuore di React è il **DOM virtuale**, che consente re-render efficienti. Quando lo state cambia, React riflette nel DOM solo le differenze, senza che sia necessario manipolarlo manualmente.

<Info>
  In questa pagina spieghiamo la combinazione di React 19 e Inertia v3. Lo starter kit di Laravel 13 usa questa configurazione per impostazione predefinita.
</Info>

### JSX e TSX

I componenti React si scrivono con la sintassi **JSX** (JavaScript XML). Puoi scrivere direttamente dentro JavaScript una notazione simile all'HTML.

```jsx theme={null}
// Esempio di JSX
function Greeting({ name }) {
    return <h1>Ciao, {name}</h1>
}
```

Negli starter kit è adottato di default **TypeScript** (`.tsx`). Le definizioni di tipo rafforzano il completamento dell'IDE e ti fanno trovare i bug in anticipo.

```tsx theme={null}
// Esempio TSX (TypeScript)
type Props = {
    name: string
}

function Greeting({ name }: Props) {
    return <h1>Ciao, {name}</h1>
}
```

<Tip>
  Lo starter kit React di Laravel usa TypeScript + TSX come standard. Anche gli esempi di questa pagina sono tutti in TSX.
</Tip>

***

## Posizione in Laravel

### Storia

Il rapporto tra React e Laravel è un po' più recente rispetto a Vue, ma oggi è del tutto paragonabile.

```mermaid theme={null}
timeline
    title Il percorso di Laravel e React
    2019 : Laravel 6 — aggiunto lo scaffold React in laravel/ui
    2021 : Laravel 8 — aggiunto lo stack Inertia React a Breeze
    2022 : Laravel 9 — passaggio a Vite
    2025 : Laravel 12 — rinnovo degli starter kit (React / Vue)
    2026 : Laravel 13 — starter kit compatibili con Inertia v3
```

Con **Laravel 6 (2019)** lo scaffold di autenticazione è stato scorporato nel pacchetto `laravel/ui` e sono stati offerti scaffold sia per Vue sia per React. All'epoca però Vue era dominante e la presenza di React era limitata.

Con l'aggiunta dello stack Inertia + React a **Laravel Breeze (2021)** è iniziata un'adozione seria; con il rinnovo degli starter kit di **Laravel 12 (2025)** React è stato trattato completamente allo stesso livello di Vue (anzi, viene mostrato per primo).

### Stile principale attuale: Inertia × React

Il modo principale di usare React in Laravel oggi è **Inertia × React**. Inertia realizza un'architettura "monolite moderno" in cui puoi passare dati dai controller Laravel direttamente ai componenti React senza progettare un'API.

```mermaid theme={null}
graph LR
    Browser["Browser"]
    Inertia["Inertia.js<br>(layer adapter)"]
    Laravel["Laravel<br>(controller)"]
    React["React<br>(componenti pagina)"]

    Browser <-->|XHR / full page load| Inertia
    Inertia <-->|Risposta Inertia| Laravel
    Inertia -->|props| React
    React -->|rendering| Browser
```

***

## Setup

### Tramite starter kit (consigliato)

Per iniziare un nuovo progetto, il modo più semplice è usare lo starter kit.

```shell theme={null}
laravel new my-app
```

Se scegli **React** nel prompt interattivo, viene tutto configurato automaticamente.

* `inertiajs/inertia-laravel` (adapter lato server)
* `@inertiajs/react` (adapter lato client)
* `react` + `react-dom` (React 19)
* `@vitejs/plugin-react` (plugin Vite)
* TypeScript + `@types/react`
* Tailwind CSS + libreria di componenti shadcn/ui
* Middleware `HandleInertiaRequests`
* Schermate di autenticazione (login, registrazione, ecc.) già implementate con Inertia + React + TypeScript

### Installazione manuale

Se vuoi aggiungerlo a un progetto esistente, installa separatamente lato server e lato client.

```shell theme={null}
# Lato server (PHP)
composer require inertiajs/inertia-laravel

# Lato client (JavaScript)
npm install @inertiajs/react react react-dom
npm install --save-dev @vitejs/plugin-react @types/react @types/react-dom typescript
```

Aggiungi poi il plugin React in `vite.config.ts`.

```ts theme={null}
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'
import react from '@vitejs/plugin-react'

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.tsx'],
            refresh: true,
        }),
        react(),
    ],
})
```

Avvia l'app Inertia in `resources/js/app.tsx`.

```tsx theme={null}
import { createInertiaApp } from '@inertiajs/react'
import { createRoot } from 'react-dom/client'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'

createInertiaApp({
    resolve: (name) =>
        resolvePageComponent(
            `./pages/${name}.tsx`,
            import.meta.glob('./pages/**/*.tsx'),
        ),
    setup({ el, App, props }) {
        createRoot(el).render(<App {...props} />)
    },
})
```

<Info>
  Per i dettagli dell'installazione manuale (configurazione del template root, registrazione dei middleware, ecc.) consulta la [documentazione ufficiale di Inertia](https://inertiajs.com/installation).
</Info>

***

## Struttura delle directory

Negli starter kit i componenti pagina React vanno nella directory `resources/js/pages/`.

```
resources/js/
├── app.tsx            # Entry point dell'app Inertia
├── bootstrap.ts
├── components/        # Componenti UI riutilizzabili
│   ├── ui/            # Componenti shadcn/ui
│   └── ...
├── hooks/             # Hook React personalizzati
├── layouts/           # Componenti di layout
│   ├── app-layout.tsx
│   └── auth-layout.tsx
├── lib/               # Funzioni utility e configurazione
├── pages/             # Componenti pagina Inertia (corrispondono ai nomi dei controller)
│   ├── auth/
│   │   ├── login.tsx
│   │   └── register.tsx
│   ├── dashboard.tsx
│   └── posts/
│       ├── index.tsx
│       ├── create.tsx
│       └── show.tsx
└── types/             # Definizioni di tipo TypeScript
```

Scrivendo `Inertia::render('posts/index', [...])`, il componente corrispondente è `resources/js/pages/posts/index.tsx`.

***

## Basi della sintassi JSX

React usa JSX. Ecco i pattern minimi da conoscere per leggere il codice degli starter kit, uno stile in cui si scrive sintassi simile all'HTML dentro JavaScript.

#### `{}` — espansione di variabile

In JSX si usa `{}` per incorporare valori o espressioni JavaScript.

```tsx theme={null}
const name = 'mondo'
const count = 3

return (
    <div>
        <p>Ciao, {name}!</p>
        <p>Il doppio è {count * 2}</p>
    </div>
)
```

#### Condizionali — `&&` e operatore ternario

React non ha una direttiva equivalente a `v-if`. Per condizioni semplici si usa l'operatore `&&`, per if/else l'operatore ternario `? :`.

```tsx theme={null}
{/* Mostra solo se la condizione è true */}
{isLoggedIn && <p>Benvenuto!</p>}

{/* if / else */}
{isLoggedIn ? <p>Benvenuto!</p> : <a href="/login">Login</a>}

{/* if / else if / else */}
{isLoggedIn
    ? <p>Benvenuto!</p>
    : role === 'admin'
        ? <p>Loggato come amministratore</p>
        : <a href="/login">Login</a>
}
```

#### Rendering di liste — `.map()`

Per il rendering di liste si usa `Array.map()`. Specifica sempre la prop `key` per un aggiornamento differenziale efficiente.

```tsx theme={null}
<ul>
    {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
    ))}
</ul>
```

Corrisponde a `v-for :key` di Vue e a `{#each}` di Svelte.

#### `className` — nome della classe CSS

Poiché JSX viene compilato in JavaScript, `class` è una parola riservata. Per le classi CSS si usa `className`.

```tsx theme={null}
{/* HTML: <div class="container"> */}
<div className="container">...</div>
```

#### Gestori di eventi — camelCase

Gli attributi evento in JSX sono in camelCase e ricevono un riferimento a una funzione.

```tsx theme={null}
<button onClick={handleClick}>Clicca</button>

{/* Annulla il comportamento predefinito di submit */}
<form onSubmit={(e) => { e.preventDefault(); handleSubmit() }}>
    ...
</form>
```

***

## Le basi del componente pagina

I componenti pagina di Inertia sono normali componenti React. I dati passati dal controller Laravel vengono ricevuti come props.

### Controller

```php theme={null}
// app/Http/Controllers/PostController.php
use Inertia\Inertia;
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        return Inertia::render('posts/index', [
            'posts' => Post::latest()->paginate(10),
        ]);
    }
}
```

### Componente pagina React

```tsx theme={null}
// resources/js/pages/posts/index.tsx
import { Link } from '@inertiajs/react'

type Post = {
    id: number
    title: string
    created_at: string
}

type Props = {
    posts: {
        data: Post[]
        // paginate(10) restituisce un oggetto con le informazioni di paginazione
        // Sono disponibili anche current_page, last_page, per_page, total, ecc.
    }
}

export default function PostsIndex({ posts }: Props) {
    return (
        <div>
            <h1>Elenco dei post</h1>
            {posts.data.map((post) => (
                <article key={post.id}>
                    <h2>
                        <Link href={`/posts/${post.id}`}>{post.title}</Link>
                    </h2>
                    <p>{post.created_at}</p>
                </article>
            ))}
        </div>
    )
}
```

Ricevendo le props come argomento del componente, puoi usare direttamente i dati passati dal controller. Non serve definire un'API REST.

***

## Componente `Link`

Usando il componente `<Link>` di `@inertiajs/react`, le transizioni di pagina avvengono via XHR ed eviti il full reload del browser.

```tsx theme={null}
import { Link } from '@inertiajs/react'

export default function PostsIndex() {
    return (
        <div>
            {/* Link di base */}
            <Link href="/posts">Elenco post</Link>

            {/* Link con metodo POST (ad es. per l'eliminazione) */}
            <Link href="/posts/1" method="delete" as="button">
                Elimina
            </Link>

            {/* Preload (fetch anticipato all'hover) */}
            <Link href="/posts/1" preload>
                Vedi il post
            </Link>
        </div>
    )
}
```

Si scrive esattamente come un normale tag `<a>`, ma dietro le quinte Inertia sostituisce solo il componente di pagina, dando una sensazione da SPA.

***

## Componente `Form`

Il componente `<Form>` fornito da `@inertiajs/react` è lo stile consigliato per l'invio dei form, usato nelle schermate di autenticazione degli starter kit. Specifichi `action` e `method` come props e ricevi `errors` e `processing` tramite una funzione children (render prop).

### Uso di base

```tsx theme={null}
import { Form } from '@inertiajs/react'

export default function PostCreate() {
    return (
        <Form action="/posts" method="post" className="flex flex-col gap-4">
            {({ errors, processing }) => (
                <>
                    <div>
                        <label htmlFor="title">Titolo</label>
                        <input id="title" name="title" type="text" required />
                        {errors.title && <p className="error">{errors.title}</p>}
                    </div>

                    <div>
                        <label htmlFor="content">Contenuto</label>
                        <textarea id="content" name="content" />
                        {errors.content && <p className="error">{errors.content}</p>}
                    </div>

                    <button type="submit" disabled={processing}>
                        {processing ? 'Invio in corso...' : 'Pubblica'}
                    </button>
                </>
            )}
        </Form>
    )
}
```

Il children di `<Form>` è una funzione `({ errors, processing }) => JSX` (pattern render prop). Il componente `Form` calcola e passa automaticamente questi valori. Ai campi del form si assegna l'attributo nativo HTML `name` invece di un handler `onChange`, così la raccolta standard dei dati del browser funziona.

### Pattern degli starter kit

Gli starter kit gestiscono le rotte come oggetti tramite [Wayfinder](/it/blog/wayfinder-introduction). `store.form()` restituisce un oggetto che contiene `action` e `method` dell'oggetto rotta e lo si passa a `<Form>` con lo spread.

```tsx theme={null}
import { Form } from '@inertiajs/react'
import { store } from '@/routes/login'

export default function Login() {
    return (
        <Form
            {...store.form()}
            resetOnSuccess={['password']}
            className="flex flex-col gap-6"
        >
            {({ errors, processing }) => (
                <>
                    {/* Contenuto del form */}
                </>
            )}
        </Form>
    )
}
```

I campi specificati in `resetOnSuccess` vengono ripristinati automaticamente in caso di invio riuscito. Impostalo per campi come la password che vuoi svuotare dopo l'invio.

<Info>
  Se non usi Wayfinder puoi passare direttamente l'URL come `action="/login"` e funziona allo stesso modo.
</Info>

***

## Hook `useForm`

Per la gestione dei form si usa l'hook `useForm` di `@inertiajs/react`. Puoi implementare in modo semplice gestione dello stato, invio e visualizzazione degli errori di validazione.

### Lato controller

```php theme={null}
// app/Http/Controllers/PostController.php
class PostController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
        ]);

        Post::create($validated + ['user_id' => auth()->id()]);

        return redirect()->route('posts.index')
            ->with('success', 'Post creato.');
    }
}
```

### Componente form React

```tsx theme={null}
// resources/js/pages/posts/create.tsx
import { useForm } from '@inertiajs/react'
import { FormEventHandler } from 'react'

export default function PostCreate() {
    const { data, setData, post, processing, errors } = useForm({
        title: '',
        content: '',
    })

    const submit: FormEventHandler = (e) => {
        e.preventDefault()
        post('/posts')
    }

    return (
        <form onSubmit={submit}>
            <div>
                <label>Titolo</label>
                <input
                    type="text"
                    value={data.title}
                    onChange={(e) => setData('title', e.target.value)}
                />
                {errors.title && <p className="error">{errors.title}</p>}
            </div>

            <div>
                <label>Contenuto</label>
                <textarea
                    value={data.content}
                    onChange={(e) => setData('content', e.target.value)}
                />
                {errors.content && <p className="error">{errors.content}</p>}
            </div>

            <button type="submit" disabled={processing}>
                {processing ? 'Invio in corso...' : 'Pubblica'}
            </button>
        </form>
    )
}
```

Ecco le principali proprietà restituite da `useForm`.

| Proprietà / Metodo      | Descrizione                                                 |
| ----------------------- | ----------------------------------------------------------- |
| `data`                  | Oggetto dati del form                                       |
| `setData(field, value)` | Aggiorna il valore di un campo                              |
| `errors`                | Errori di validazione (accesso per nome campo)              |
| `processing`            | `true` durante l'invio (utile per disabilitare il pulsante) |
| `isDirty`               | `true` se ci sono modifiche rispetto ai valori iniziali     |
| `post(url)`             | Invia con richiesta POST                                    |
| `put(url)`              | Invia con richiesta PUT (update)                            |
| `delete(url)`           | Invia con richiesta DELETE                                  |
| `reset()`               | Ripristina il form ai valori iniziali                       |

Quando arrivano errori di validazione, `useForm` mostra gli errori mantenendo i contenuti inseriti.

***

## Dati condivisi (Shared Data)

I dati necessari a tutte le pagine (utente loggato, messaggi flash, ecc.) si definiscono nel metodo `share()` del middleware `HandleInertiaRequests`.

```php theme={null}
// app/Http/Middleware/HandleInertiaRequests.php
use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'auth' => [
                'user' => $request->user()
                    ? $request->user()->only('id', 'name', 'email')
                    : null,
            ],
            'flash' => [
                'success' => $request->session()->get('success'),
                'error'   => $request->session()->get('error'),
            ],
        ]);
    }
}
```

Per accedere ai dati condivisi da un componente React, usa l'hook `usePage()`.

```tsx theme={null}
import { usePage } from '@inertiajs/react'

type SharedProps = {
    auth: {
        user: { id: number; name: string; email: string } | null
    }
    flash: {
        success: string | null
        error: string | null
    }
}

export default function AppHeader() {
    const { auth, flash } = usePage<SharedProps>().props

    return (
        <>
            <header>
                {auth.user ? (
                    <span>{auth.user.name}</span>
                ) : (
                    <span>Ospite</span>
                )}
            </header>

            {flash.success && (
                <div className="alert-success">{flash.success}</div>
            )}
        </>
    )
}
```

<Info>
  Poiché i dati condivisi sono inclusi in ogni richiesta, si consiglia di limitarli allo stretto necessario. Usando valutazioni lazy con `fn()`, vengono valutati solo quando ci si accede davvero.
</Info>

***

## Basi degli hook React

Ecco gli hook React essenziali per sviluppare con Inertia × React.

### `useState` — gestione dello stato locale

```tsx theme={null}
import { useState } from 'react'

export default function Counter() {
    const [count, setCount] = useState(0)
    const [isOpen, setIsOpen] = useState(false)

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
        </div>
    )
}
```

### `useEffect` — gestione degli effetti collaterali

```tsx theme={null}
import { useState, useEffect } from 'react'

export default function Timer() {
    const [seconds, setSeconds] = useState(0)

    useEffect(() => {
        const timer = setInterval(() => {
            setSeconds((s) => s + 1)
        }, 1000)

        // Funzione di cleanup
        return () => clearInterval(timer)
    }, []) // Array vuoto = eseguito una sola volta al mount

    return <p>Tempo trascorso: {seconds}s</p>
}
```

### `useMemo` e `useCallback` — ottimizzazione delle prestazioni

```tsx theme={null}
import { useMemo, useCallback } from 'react'
import { router } from '@inertiajs/react'

type Post = { id: number; title: string; published: boolean }
type Props = { posts: Post[] }

export default function PostsList({ posts }: Props) {
    // Memoizza il valore (non ricalcola finché posts non cambia)
    const publishedPosts = useMemo(
        () => posts.filter((post) => post.published),
        [posts],
    )

    // Memoizza la funzione (non la ricrea finché non cambiano le dipendenze)
    const handleClick = useCallback((id: number) => {
        router.visit(`/posts/${id}`)
    }, [])

    return (
        <ul>
            {publishedPosts.map((post) => (
                <li key={post.id} onClick={() => handleClick(post.id)}>
                    {post.title}
                </li>
            ))}
        </ul>
    )
}
```

***

## Supporto TypeScript

Lo starter kit React usa TypeScript di default. Combinandolo con le definizioni di tipo di Inertia puoi garantire la type-safety delle prop.

### Definizioni di tipo globali

Negli starter kit i tipi dei dati condivisi si definiscono in `resources/js/types/index.d.ts`.

```ts theme={null}
// resources/js/types/index.d.ts
export interface User {
    id: number
    name: string
    email: string
    email_verified_at?: string
}

export type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
    auth: {
        user: User
    }
}
```

### Uso dei tipi nel componente pagina

```tsx theme={null}
import { PageProps } from '@/types'

type Post = {
    id: number
    title: string
    content: string
}

export default function PostsIndex({ auth, posts }: PageProps<{ posts: Post[] }>) {
    return (
        <div>
            <p>Loggato come: {auth.user.name}</p>
            {posts.map((post) => (
                <article key={post.id}>
                    <h2>{post.title}</h2>
                </article>
            ))}
        </div>
    )
}
```

***

## Conclusioni

React dà il meglio in combinazione con Laravel, in particolare nella configurazione "monolite moderno" tramite Inertia. È anche molto compatibile con TypeScript e adatto allo sviluppo di applicazioni di grandi dimensioni.

| Elemento                | Ruolo                                                 |
| ----------------------- | ----------------------------------------------------- |
| Controller Laravel      | Routing, recupero dati e validazione                  |
| `Inertia::render()`     | Passa i dati dal controller al componente React       |
| Componente pagina React | Riceve le prop e renderizza la UI                     |
| `useForm`               | Gestione stato, invio ed errori del form              |
| Componente `Link`       | Transizioni di pagina senza full reload               |
| `usePage().props`       | Accesso ai dati condivisi                             |
| TypeScript              | Type-safety delle prop e completamento IDE potenziato |

Usando Inertia × React ottieni un'esperienza di sviluppo che combina la semplicità del backend Laravel con il potente ecosistema di React. Creando il progetto tramite starter kit, puoi iniziare subito con schermate di autenticazione incluse.

<Card title="Documentazione ufficiale di Inertia.js" icon="book-open" href="https://inertiajs.com">
  Per tutte le funzionalità di Inertia v3 consulta la documentazione ufficiale.
</Card>


## Related topics

- [Introduzione a Svelte — le basi per usarlo con Inertia × Laravel](/it/blog/svelte-introduction.md)
- [Introduzione a Vue.js — le basi per usarlo con Inertia × Laravel](/it/blog/vue-introduction.md)
- [Frontend](/it/frontend.md)
- [Costruire una SPA con Inertia.js](/it/blog/inertia-introduction.md)
- [Conoscenze necessarie prima di iniziare con Laravel](/it/true-tutorial.md)
