Live view and handle info
Phoenix LiveView handle_info Guide for Web Developers
What is handle_info?
handle_info is Phoenix LiveView's way of handling messages sent to the LiveView process from outside normal user interactions (like clicks). It's your LiveView's inbox for asynchronous events.
In traditional web development, everything is request-response: user clicks, server responds, done. But LiveView processes are long-running and can receive messages from other parts of your system while they're alive.
Basic Syntax
def handle_info(message, socket) do
# Process the message
# Update socket state if needed
{:noreply, socket}
end
Example 1: Timer (sending to self)
The simplest way to trigger handle_info - send a message to yourself:
defmodule AppWeb.PageLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
Process.send_after(self(), :refresh, 5000)
{:ok, socket}
end
def handle_info(:refresh, socket) do
IO.inspect("Message received after 5 seconds!")
{:noreply, socket}
end
def render(assigns) do
~H"""
Page
"""
end
end
Example 2: Sending Between LiveViews with PubSub
This is the recommended way to send messages between LiveViews.
In PageLive (the receiver):
defmodule AppWeb.PageLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(App.PubSub, "events")
end
{:ok, socket}
end
def handle_info(:my_message, socket) do
IO.inspect("handle_info received!")
{:noreply, socket}
end
def render(assigns) do
~H"""
Page
"""
end
end
In HomeLive (the sender):
defmodule AppWeb.HomeLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, socket}
end
def handle_event("trigger_page", _params, socket) do
Phoenix.PubSub.broadcast(App.PubSub, "events", :my_message)
{:noreply, socket}
end
def render(assigns) do
~H"""
<button phx-click="trigger_page">Trigger Page handle_info</button>
"""
end
end
Why do you need both subscribe AND broadcast?
- Subscribe = "I want to listen to messages on the 'events' topic"
- Broadcast = "Send this message to everyone listening to 'events'"
Without subscribe, the LiveView won't receive broadcasts. Think of it like tuning a radio to a channel - you must tune in (subscribe) before you can hear what's being transmitted (broadcast).
PubSub works with multiple LiveViews
If you have 3 PageLive tabs open, all 3 will receive the broadcast. That's a feature, not a bug.
Example 3: Process Registration (not recommended)
You can register a LiveView process with a name and send directly to it:
In PageLive:
defmodule AppWeb.PageLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket) do
Process.register(self(), :page_live_process)
end
{:ok, socket}
end
def handle_info(:my_message, socket) do
IO.inspect("handle_info received!")
{:noreply, socket}
end
def render(assigns) do
~H"""
Page
"""
end
end
In HomeLive:
defmodule AppWeb.HomeLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, socket}
end
def handle_event("send_to_page", _params, socket) do
send(:page_live_process, :my_message)
{:noreply, socket}
end
def render(assigns) do
~H"""
<button phx-click="send_to_page">Send to Page</button>
"""
end
end
Problems with this approach:
- Only works with ONE PageLive instance at a time
- Crashes if name is already taken
- Requires error handling bloat
- PageLive must be mounted first
Use PubSub instead - it's simpler and more robust.
Common Sources of Messages
handle_info receives messages from:
- Timers:
Process.send_after(self(), :tick, 1000) - PubSub broadcasts:
Phoenix.PubSub.broadcast(App.PubSub, "topic", :msg) - Other processes:
send(liveview_pid, :msg) - Tasks: Background jobs completing
- GenServers: Other parts of your application
Safety: Catch-all handle_info
Always add a catch-all to prevent crashes from unexpected messages:
def handle_info(msg, socket) do
IO.warn("Unhandled message: #{inspect(msg)}")
{:noreply, socket}
end
Key Takeaways
- handle_info handles asynchronous messages sent to your LiveView
- Use
send(self(), :msg)to send messages to yourself - Use PubSub (not process registration) to send between LiveViews
- You must subscribe to a topic before you can receive broadcasts on that topic
- Always include a catch-all handle_info to handle unexpected messages