Going further
Rendering
Nitro's rendering is fine-grained. Each dynamic part of a view knows which properties it reads, so when a property changes, only those parts run and only their nodes change. Nothing is compared.
On this page
When Nitro compiles a view, every dynamic part of it records which properties it reads. A dynamic part
is an echo, an attribute, an @if, a @foreach or a child's props. When a
property changes, only the parts that read it run again, and each one updates its own node.
- Ada
- Alan
- Barbara
- Donald
- Edsger
- Frances
- Grace
- Hedy
- Ivan
- Joan
- Ken
- Linus
- Margaret
- Niklaus
- Radia
- Shafi
- Sophie
- Tim
- Vint
- Whitfield
Click, type or add an author: what changes flashes.
Click +, and only one number flashes. Type a name, and only the greeting changes. Add an author, and one new row is added while the twenty rows already there are left alone.
The component
<?php
namespace App\Nitro\Components;
use Nitro\Component;
class RenderDemo extends Component
{
public int $count = 0;
public string $name = 'Ada';
public array $authors = [
'Ada', 'Alan', 'Barbara', 'Donald', 'Edsger', 'Frances', 'Grace', 'Hedy', 'Ivan', 'Joan',
'Ken', 'Linus', 'Margaret', 'Niklaus', 'Radia', 'Shafi', 'Sophie', 'Tim', 'Vint', 'Whitfield',
];
public function increment(): void
{
$this->count++;
}
public function addAuthor(): void
{
$this->authors[] = 'Author '.(count($this->authors) + 1);
}
}
<div data-flash-updates class="w-full max-w-xl space-y-3 text-sm">
<div class="flex flex-wrap items-center gap-3">
<button type="button" nitro:click="increment" class="rounded-lg bg-slate-900 px-3 py-1.5 font-semibold text-white dark:bg-white dark:text-slate-900">+</button>
<span>Clicked <strong>{{ $count }}</strong> times</span>
<input nitro:model="name" class="w-32 rounded-lg bg-white px-2 py-1 ring-1 ring-slate-300 outline-none dark:bg-slate-900 dark:ring-white/15" aria-label="Name">
<span>Hello, {{ $name }}</span>
<button type="button" nitro:click="addAuthor" class="rounded-lg px-3 py-1.5 ring-1 ring-slate-300 dark:ring-white/15">Add an author</button>
</div>
<ul class="grid grid-cols-4 gap-1 sm:grid-cols-5">
@foreach ($authors as $i => $author)
<li nitro:key="{{ $i }}" class="truncate rounded bg-slate-100 px-2 py-1 dark:bg-white/5">{{ $author }}</li>
@endforeach
</ul>
<p data-flash-count nitro:ignore class="text-xs text-slate-500">Click, type or add an author: what changes flashes.</p>
</div>
Compiling…
How Nitro tracks what each part reads
Each highlighted line below reads one property, so it runs again only when that property changes:
<div>
<button nitro:click="increment">+</button>
<p>Clicked {{ $count }} times</p> {{-- reads $count --}}
<p>Hello, {{ $name }}</p> {{-- reads $name, so a click leaves it alone --}}
@foreach ($authors as $author) {{-- reads $authors, so neither one changes it --}}
<li>{{ $author }}</li>
@endforeach
</div>
Here is how this compares with other frameworks, when one property changes:
| What runs again | What is compared | |
|---|---|---|
| Livewire | The whole view, on the server | The new HTML against the page |
| React, Vue | The component's render function | The new virtual DOM against the last one |
| Nitro | The expressions that read the property | Nothing. Each expression updates its own node |
- Methods are followed. Nitro works out what a part reads at compile time, through the methods it calls. An echo of
$this->total()reads whatevertotal()reads. #[Computed]values are cached until the state they read changes.$errors,$this->shared()and$this->flashed()are tracked just like properties.- Updates from the server work the same way. A
#[Server]answer, a reload or a parent's new props only render the parts that read what changed. - Keyed lists (
nitro:key,:key) move, add and remove rows, and leave the other rows alone.
Choosing how elements are created
The browser creates new elements when you visit a page, when an @if turns true, or when a list
gains rows. The nitro.rendering setting decides how it creates them. The result is the same
either way, and the first page load always uses the server's HTML as it is.
// config/nitro.php
'rendering' => 'clone', // Or 'create'.
| Setting | How elements are created |
|---|---|
'clone'
(default)
|
Each static part of a view is built once, then copied |
'create'
|
Every element is created one by one |