Hello! Welcome to the final lesson in our module on real-time applications with Laravel.
In our last session, we successfully configured Laravel Echo on the client-side. You learned how to subscribe to public, private, and presence channels and saw how to receive broadcasted events in your browser's JavaScript console. The entire pipeline from backend event to frontend listener is now in place.
Today, we'll complete the circle. We'll move beyond console.log and learn how to use the data from these events to create truly dynamic user interfaces. This lesson is all about making changes to the web page—adding, updating, or removing elements—in direct response to server events, all without a single page refresh.
By the end of this lesson, you will be able to take a broadcasted event and use its data to dynamically update a UI component, bringing your application to life.
1. From Event Data to DOM Manipulation
The fundamental process is straightforward:
- Listen: Your Laravel Echo listener waits for a specific event on a channel.
- Receive: When the event arrives, the callback function you defined is executed, receiving an event object containing the payload from your Laravel backend.
- Update: Your JavaScript code uses this payload to manipulate the Document Object Model (DOM), changing what the user sees on the page.
How you perform step 3 depends heavily on your application's frontend stack. We will explore two of the most common patterns in the Laravel world:
- Using a client-side JavaScript framework (like React or Vue, often with Inertia.js).
- Using Laravel Livewire (which allows you to control the UI primarily from your PHP backend).
Let's look at a practical, end-to-end example of the first approach.
Laravel Reverb: The Easiest Way to Add Real-Time Magic to Your App
First, let's see the goal. This video by Glenn Raya demonstrates a common real-time feature: an editor requests an article deletion, a chief editor approves it, and the article list on the editor's screen updates instantly.
Watch the short demonstration from 00:44 to 01:54 to understand the real-time UI updates we'll be dissecting.
2. Approach 1: Updating the UI with a JavaScript Framework
This approach is typical when using Laravel as an API backend for a JavaScript-driven frontend (e.g., a Single Page Application or when using Inertia.js). The core principle is to update state, not the DOM directly.
In frameworks like React or Vue, you don't typically write code like document.getElementById('my-div').innerHTML = .... Instead, you update a state variable, and the framework automatically re-renders the UI to reflect the new state.
Let's see how this works.
Step 1: Receiving the Event and Updating State
As you learned in the previous lesson, you set up a listener. The key is what you do inside the callback function.
Laravel Reverb: The Easiest Way to Add Real-Time Magic to Your App
This clip continues the previous example, showing how to listen for the 'DeleteArticleRequestReceived' event and, crucially, how to use its payload to update the component's state.
Watch from 12:14 to 15:19. Notice how the useEffect hook sets up the Echo listener. Pay close attention to the callback function at 15:30. Instead of touching the DOM, it calls setNotification, which is a React state update function.
In the video, the component listens for the DeleteArticleRequestReceived event. When it arrives, the callback function is executed:
// Inside a React component
useEffect(() => {
window.Echo.private(`management.${auth.user.id}`)
.listen('DeleteArticleRequestReceived', (e) => {
// e contains the event payload from Laravel
// DON'T do this:
// const notification = document.createElement('div');
// document.body.appendChild(notification);
// DO this: Update the component's state
setNotification(e); // 'e' contains the article, chief editor, etc.
});
}, []);
By calling setNotification(e), the component is told that its data has changed. The framework then takes over and re-renders any part of the UI that depends on the notification state. This declarative approach is cleaner and less error-prone than manual DOM manipulation.
The Laravel documentation highlights a more modern and convenient way to do this using dedicated hooks for React and Vue, which also handle cleanup automatically.
Broadcasting - Using React or Vue
The official documentation provides helper hooks that simplify this process. Let's look at the useEcho hook, which encapsulates the logic of subscribing and unsubscribing from channels within a component's lifecycle.
Read the section 'Using React or Vue'. Note how the useEcho hook simplifies listening for events. It takes the channel, event name, and callback as arguments. The principle remains the same: the callback should update state.
Using the useEcho hook, the previous example becomes even cleaner:
import { useEcho } from "@laravel/echo-react";
// Inside your React component
const [notification, setNotification] = useState(null);
useEcho(`management.${auth.user.id}`, "DeleteArticleRequestReceived", (e) => {
setNotification(e);
});
Step 2: Dynamically Adding and Removing Elements
Now, let's see the final part of the flow: reacting to another event to remove an element from a list.
Laravel Reverb: The Easiest Way to Add Real-Time Magic to Your App
This final clip from the same video shows what happens after the chief editor approves the deletion. A new 'ArticleDeleted' event is broadcast, and the editor's UI listens for it to remove the article from their list.
Watch from 18:16 to 23:02. Focus on these key moments: Backend (19:42): A new ArticleDeleted event is broadcast after the article is deleted. Frontend Listener (20:39): A new listener is added for the ArticleDeleted event. State Update (21:42): The listener's callback updates the article list state by filtering out the deleted article: setArticleList(currentList => currentList.filter(item => item.id !== e.article.id)). The UI then re-renders automatically.
This demonstrates a complete "read and write" real-time cycle: one event adds a notification to the UI, and a subsequent event removes an item from a list. Both are achieved by updating the component's state, letting the framework handle the DOM updates.
3. Approach 2: Updating the UI with Laravel Livewire
Livewire offers a very different, backend-centric approach that you might find compelling as a PHP developer. Instead of writing JavaScript listeners, you declare them in your PHP component class.
The flow with Livewire is:
- An event is broadcast from your Laravel application.
- The Livewire frontend, powered by Alpine.js and Morphdom, listens for this event via Laravel Echo.
- Upon receiving the event, Livewire sends a request to your PHP Livewire component on the server, invoking a specific method.
- This PHP method updates the public properties (the "state") of the component.
- Livewire re-renders the component's Blade view on the server and sends the efficiently "diffed" HTML back to the client, which intelligently updates the DOM.
Listening for Echo Events in a Livewire Component
Livewire makes this incredibly simple with a special #[On] attribute syntax.
Real-time events using Laravel Echo
Let's review the Livewire documentation to see how to subscribe a PHP component to a real-time event from Laravel Echo.
Read the section 'Real-time events using Laravel Echo'. Pay close attention to the #[On('echo:channel,EventName')] syntax. This is the core mechanism for linking a broadcast event to a PHP method.
As the documentation shows, you simply annotate a public method in your Livewire component. For a public channel:
// In a Livewire component, e.g., app/Livewire/OrderTracker.php
use Livewire\Attributes\On;
use Livewire\Component;
class OrderTracker extends Component
{
public $showNewOrderNotification = false;
// This method will be called when 'OrderShipped' is received on the 'orders' channel
#[On('echo:orders,OrderShipped')]
public function notifyNewOrder($event) // $event contains the payload
{
// Update the component's state
$this->showNewOrderNotification = true;
// Optionally, use the payload
// logger($event['order']['id']);
}
// ... render method
}
In your corresponding Blade view (order-tracker.blade.php), you can now use this state:
<div>
@if ($showNewOrderNotification)
<div class="notification">
A new order has been shipped!
</div>
@endif
</div>
When the OrderShipped event is broadcast, the notifyNewOrder method runs, sets $showNewOrderNotification to true, and Livewire automatically updates the browser to display the notification <div>. All without you writing any custom JavaScript for the update logic.
Let's watch a practical demonstration.
Going Real-Time with Reverb - Laravel In Practice EP17
This video from Laravel News demonstrates the Livewire approach in a real-world scenario, updating a dashboard with new order information.
Watch from 06:24 to 10:19. Observe how: The Listener (08:01): The On attribute is used to link the OrderPlaced event to the handleOrder method in the PHP component. State Update (06:46): The handleOrder method increments a $liveUpdateCount property and dispatches other events. UI Reaction (09:08): The Blade template uses simple @if and Alpine.js directives (x-data, @order-received.window) to show a live indicator and flash the background of the newly added table row. This shows the powerful synergy between Livewire and Alpine.js.
Conclusion
You have now mastered the final and most visually rewarding part of event broadcasting: making the UI react in real time.
Key Takeaways:
- The goal of an Echo listener's callback is to trigger a UI update using the event's payload.
- JavaScript Framework Approach (React/Vue/Inertia): The JS listener callback updates the component's state. The framework then re-renders the DOM. This is a client-centric model.
- Laravel Livewire Approach: A
#[On('echo:...')attribute on a PHP method serves as the listener. The PHP method updates the component's public properties (its state), and Livewire handles re-rendering and sending the updated HTML to the browser. This is a backend-centric model. - Choosing between these approaches depends entirely on your project's architecture. Both are powerful and well-supported within the Laravel ecosystem.
Up Next:
We are now concluding our module on real-time applications. You've built a complete feature from backend to frontend. Now, how do you ensure it stays working as you add more features? The next module, "Production-Ready Testing," will shift our focus from building to validating. In the first lesson, we will start with the fundamentals and learn to "Differentiate between unit, feature, and integration tests."