Checking for @current_user

I’m wondering if anyone can help and explain an issue I’m experiencing with Live View 0.18 in Phoenix.

I’m using function components to compose a menu

def main_menu(assigns) do
    ~H"""
    <.slide_menu_panel>
      <div class="flex flex-col">
        <div class="w-4/5 mx-auto bg-gray-700 bg-opacity-80 text-gray-50 rounded-lg ">
          <div class="w-full border-b border-slate-600">
            <div class="p-4">
              <h2 class="font-semibold uppercase text-slate-200">Menu</h2>
            </div>
          </div>

          <%!-- menu items --%>
          <.menu_item url={~p"/"} label="Home" icon="hero-home" />

          <%= if @current_user do %>
            <%!-- Anon --%>
            <.menu_item url={~p"/users/register"} label="Register" icon="hero-user-plus" />
            <.menu_item url={~p"/users/log_in"} label="Login" icon="hero-arrow-left-on-rectangle" />
            <%!-- end Anon --%>
            <% else %>

            <%!-- Logged in  menu iotems here--%>

            <%!-- end Logged in --%>
            <% end %>

          <%!-- End menu items --%>

          <footer class="w-full h-6  border-slate-600"></footer>
        </div>
      </div>
    </.slide_menu_panel>
    """
  end

The <%= if @current_user do %> construct throws and error

key :current_user not found in: %{__changed__: nil}

Now if I use

 <%= if assigns[:current_user] do %>

everything works fine.

However, in the heex template I can still use <%= if @current_user do %>

My concern was that somewhere I read a comment that using the assigns:current_user] is not recommended.

It looks like the component can only check for presence of its own attributes. I’d really appreaciate it if anyone can throw some light on what’s going on.

Incidentally, I think Phoenix and Live View are fantastic - all credit to Jose, Chris and all the contributers.

3 Likes

When you call your component, you should always pass all assigns it might use:

<.menu current_user={@current_user}>

And then your LiveView or Controller will set it to a user (if authenticated) or nil (if not).

If you are on a page where you are sure the user is not authenticated, then you can skip passing the current_user and initialize it as:

def main_menu(assigns) do
    assigns = assign_new(assigns, :current_user, nil)

    ~H"""

But I would consider using declarative assigns and specifying a default value of nil.

Incidentally, I think Phoenix and Live View are fantastic - all credit to Jose, Chris and all the contributers.

:heart:

7 Likes

I am astounded and speechless that I got a reply so quickly - and from all people - the creator of Elixir! Thank you @josevalim. I’m very grateful for your answer and advice.

3 Likes