July 30, 2026 — The unofficial Laracon US Day 3. Get your ticket to The Vibes

You're viewing pre-release documentation — version 4.x is in beta

Features, APIs and behaviour may change before the stable release. View the stable version (3.x)

Events


Overview#

Screens react to things that happen outside a user tap — a push notification arrives, a websocket message lands, a bridge call finishes. A component listens for these native events and updates its state in response; the screen re-renders like any other state change.

This page covers listening from a component. For the async bridge-response side (calling a native API and handling its result or a custom event class), see Events.

Listening with #[On]#

Annotate a method with #[On(EventClass::class)] and it runs whenever that event fires. The method's parameters are bound by name from the event's public properties:

Copied!
use Native\Mobile\Attributes\On;
use NativePHP\Vibe\Events\MessageReceived;
 
class ChatScreen extends NativeComponent
{
public array $messages = [];
 
#[On(MessageReceived::class)]
public function onMessage(string $body, string $from): void
{
$this->messages[] = ['body' => $body, 'from' => $from];
}
}

#[On] is repeatable — stack several on one method to handle multiple events, or put several methods on the same event. Listeners are torn down automatically when the screen unmounts, so they never leak onto the next screen.

Listening with ->on()#

For a listener you register at runtime — for example inside mount(), or conditionally — use the fluent ->on() method with a closure:

Copied!
public function mount(): void
{
$this->on(OrderShipped::class, function ($event) {
$this->status = "Shipped: {$event->trackingNumber}";
});
}

Use #[On] for the common case (a fixed listener declared on the class) and ->on() when you need to wire one up dynamically.

Where events come from#

Native events originate on the device side and are delivered to whichever screen is alive: plugin events (a Vibe websocket message, a push notification tap), bridge-call completions, and any custom events an async native call resolves with. Because delivery targets the live screen, a listener only fires while its screen is on the stack.