Phoenix liveview error

I just started following the phoenix LiveView tutorial. The tutorial was a bit old so going through the changelog and discovered a few things which has changed since the last release. So I’m creating a socket here which has changed somehow.


 def mount(_session, socket) do
    {:ok, assign(socket, key: "max")}
  end

  def render(assigns) do
    ~L"""
    <h1>Hi!</h1>
    <%= assigns.key %>
    """
  end

So how do I call the key to render function I tried @key also which didn’t work and using assigns.key is getting me this error

** (exit) an exception was raised:
    ** (KeyError) key :key not found in: %{flash: %{}, live_action: nil, live_module: ReactorWeb.FooLive, socket: #Phoenix.LiveView.Socket<assigns: %Phoenix.LiveView.Socket.AssignsNotInSocket{}, changed: %{}, endpoint: ReactorWeb.Endpoint, id: "phx-FhNxUCgprLDZCwKj", parent_pid: nil, root_pid: nil, router: ReactorWeb.Router, view: ReactorWeb.FooLive, ...>}
        (reactor 0.1.0) lib/reactor_web/live/foo_live.ex:11: anonymous fn/2 in ReactorWeb.FooLive.render/1
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:221: Phoenix.LiveView.Diff.traverse/5
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:92: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:284: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:144: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/controller.ex:35: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.5.3) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
        (reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.plug_builder_call/2
        (reactor 0.1.0) lib/plug/debugger.ex:132: ReactorWeb.Endpoint."call (overridable 3)"/2
        (reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.call/2
        (phoenix 1.5.3) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:320: :cowboy_stream_h.execute/3
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:302: :cowboy_stream_h.request_process/3
        (stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

:wave:

I tried @key also which didn’t work

Did you try it this way? What exactly didn’t work?

def render(assigns) do
    ~L"""
    <h1>Hi!</h1>
    <%= @key %>
    """
  end

getting this

** (exit) an exception was raised:
    ** (ArgumentError) assign @key not available in eex template.

Please make sure all proper assigns have been set. If this
is a child template, ensure assigns are given explicitly by
the parent template as they are not automatically forwarded.

Available assigns: [:flash, :live_action, :live_module, :socket]

        (phoenix_live_view 0.13.0) lib/phoenix_live_view/engine.ex:860: Phoenix.LiveView.Engine.fetch_assign!/2
        (reactor 0.1.0) lib/reactor_web/live/foo_live.ex:11: anonymous fn/2 in ReactorWeb.FooLive.render/1
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:221: Phoenix.LiveView.Diff.traverse/5
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:92: Phoenix.LiveView.Diff.render/3
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:284: Phoenix.LiveView.Static.to_rendered_content_tag/4
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:144: Phoenix.LiveView.Static.render/3
        (phoenix_live_view 0.13.0) lib/phoenix_live_view/controller.ex:35: Phoenix.LiveView.Controller.live_render/3
        (phoenix 1.5.3) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
        (reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.plug_builder_call/2
        (reactor 0.1.0) lib/plug/debugger.ex:132: ReactorWeb.Endpoint."call (overridable 3)"/2
        (reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.call/2
        (phoenix 1.5.3) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:320: :cowboy_stream_h.execute/3
        (cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:302: :cowboy_stream_h.request_process/3
        (stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Shouldn’t it be mount/3? https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#c:mount/3

So.

def mount(_params, _session, socket) do
...
end

Yes. Thanks

In order to catch issues like that in the future you can tag your functions with @impl:

@impl Phoenix.LiveView
def mount(_session, socket) do
   {:ok, assign(socket, key: "max")}
end

@impl Phoenix.LiveView
def render(assigns) do
  ~L"""
  <h1>Hi!</h1>
  <%= assigns.key %>
  """
end

The code above would give you a warning that mount/2 is not a callback (because you want mount/3 instead).

Just saying, @impl does not doe anything, unless your Editor recongnizes it.
Neither will @impl Phoenix.LiveView

The compiler will warn in your terminal

1 Like

Yes. I noticed this.

No, as Chris mentioned you do get compilation warnings (in your editor or terminal) when using @impl. What happened in this case is that mount/3 is an optional callback, which means that even though you have @behaviour Phoenix.LiveView (inserted for you by use Phoenix.LiveView). So if you instead wrote your mount function like:

  @impl Phoenix.LiveView
  def mount(_, socket) do
    {:ok, socket}
  end

Then you will get a compilation warning like:

[Warn  - 8:40:50 AM] warning: got "@impl Phoenix.LiveView" for function mount/2 but this behaviour does not 
specify such callback. The known callbacks are:

  * Phoenix.LiveView.handle_call/3 (function)
  * Phoenix.LiveView.handle_event/3 (function)
  * Phoenix.LiveView.handle_info/2 (function)
  * Phoenix.LiveView.handle_params/3 (function)
  * Phoenix.LiveView.mount/3 (function)
  * Phoenix.LiveView.render/1 (function)
  * Phoenix.LiveView.terminate/2 (function)

Which is telling you that mount/2 is not a callback and mount/3 is a valid callback. Because of these types of potential errors, when I write code I always use the equivalent of @impl Phoenix.LiveView (personally I don’t like using @impl true).