Reputation: 3825
I'm writing a ClockComponent to learn about Phoenix LiveComponents. I almost have it, but it's sending the :tick message to its parent. How can I get it to send that message to itself? I wanted to use myself()
instead of self()
but apparently that's not a thing.
defmodule ClockComponent do
use Phoenix.LiveComponent
@impl true
def mount(socket) do
if connected?(socket), do: :timer.send_interval(1000, self(), :tick)
{:ok, assign(socket, date: :calendar.local_time())}
end
def handle_info(:tick, socket) do
{:noreply, assign(socket, date: :calendar.local_time())}
end
@impl true
def render(assigns) do
~L"""
The time is <%= @date |> Timex.to_datetime("America/Denver") |> Timex.format!("{RFC1123}") %>
"""
end
end
Upvotes: 8
Views: 2749
Reputation: 25029
You can replicate the same behaviour using send_update/3
(or send_update_after/4
for calling after a set amount of time). These will call the update
function of the specified module, with the specified arguments.
eg.
defmodule ClockComponent do
use Phoenix.LiveComponent
@impl true
def mount(socket) do
if connected?(socket), do: tick()
{:ok, assign(socket, id: "clock", date: :calendar.local_time())}
end
@impl true
def update(%{action: :tick}, socket) do
tick()
{:ok, assign(socket, date: :calendar.local_time())}
end
@impl true
def update(assigns, socket) do
{:ok, assign(socket, assigns)}
end
@impl true
def render(assigns) do
~L"""
The time is <%= @date |> Timex.to_datetime("America/Denver") |> Timex.format!("{RFC1123}") %>
"""
end
# This is where the magic happens!
defp tick() do
send_update_after(__MODULE__, %{id: "clock", action: :tick}, 1000)
end
end
Upvotes: 3
Reputation: 5462
I don't think you can based on this: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html#module-managing-state
Components run inside the LiveView process, but may have their own state and event handling.
I believe both "child component" and parent share the same process.
Upvotes: 6