Після кожної дії Livewire за замовчуванням рендерить шаблон компонента заново й відправляє HTML у браузер. Для дій, що нічого не змінюють на екрані, це зайва робота: виконання Blade, обчислювані властивості й запити в шаблоні, розмір відповіді, морфінг DOM.
#[Renderless] - дія без рендеру:
use Livewire\Attributes\Renderless;
new class extends Component {
public Post $post;
#[Renderless]
public function trackRead(): void
{
$this->post->increment('reads');
}
};
<div wire:intersect.once="trackRead">...</div>
Інші способи:
$this->skipRender()усередині методу - коли рендер треба пропустити за умовою:
public function saveDraft(): void
{
$this->post->update(['draft' => $this->draft]);
if (! $this->showSavedAt) {
$this->skipRender(); // показувати нічого не треба - рендер зайвий
}
}
- модифікатор
.renderlessу шаблоні - точково, без зміни класу:wire:click.renderless="trackClick",wire:model.live.renderless="draft".
Типові застосування:
- аналітика й лічильники (перегляди, кліки, час на сторінці);
- збереження чернетки чи налаштувань, які вже відображені в браузері (стан у полі чи в Alpine);
- дії, результат яких обробляє JavaScript (повернене значення з
await $wire.method()).
Пастки:
- зміни властивостей у такій дії не з'являться на екрані - шаблон не рендерився. Якщо дія змінює те, що показується, рендер потрібен;
- помилки валідації в дії без рендеру теж не відобразяться через
@error- для таких випадків потрібен рендер чи обробка в JavaScript; - стан компонента все одно оновлюється - новий знімок повертається в браузер, тож наступні дії бачитимуть змінені значення.
Поєднання з #[Async] - класична пара для «запустив і забув»: дія не стає в чергу за іншими й не перемальовує компонент.
Тести: ->call('trackRead')->assertRenderSkipped().