Hello,
I’m working on implementing LiveView (0.13+, phx 1.5.3) on a “news” page where SEO is important and we need to implement some liveview features.
The liveview is in router.ex:
scope "/", MyAppWeb do
pipe_through :browser
...
live "/news/:slug", ShowNewsLive
...
end
The browser pipeline sets the session key “current_user_id” with the user, if present, and I would expect to rely on this in the liveview to load the user from the database.
In my liveview file (simplified):
ShowNewsLive.ex
mount(%{"slug" => slug}, %{"current_user_id" => user_id} = session, socket) do
# Load user and assign to socket.
socket =
socket
|> assign_user(session)
{:ok, socket}
end
assign_user
properly sets the current user to socket.assigns.current_user, and is available as @current_user
in my template as I would expect based on the first time mount/3 is called on HTTP connect.
However, when the js fires and the websocket connects and mount/3 is called, the session field passed to mount/3 is an empty map. Is this expected? Does the websocket connection skip the router pipeline that the http request goes through?
Secondly, the socket passed to mount/3 the second time (on websocket connect) does not have the assigns that were assigned properly earlier on the HTTP-request triggered mount/3.
In my logs, I see something like this:
[info] Sent 200 in 5ms
[info] CONNECTED TO Phoenix.LiveView.Socket in 189µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "RB0GMy0wYhFeBwpPMHhFPB5bahlpKQUwtzekhTRFlQ3bzK6qPnYr8eDV", "_mounts" => "0", "vsn" => "2.0.0"}
The following is from mount(_params, session, socket) defined after mount/3 that pattern matches for 'current_user_id' in passed session
session:
%{}
socket:
%Phoenix.LiveView.Socket{
assigns: %{flash: %{}, live_action: nil, live_module: MyAppWeb.ShowNewsLive},
changed: %{},
connected?: true,
endpoint: MyAppWeb.Endpoint,
fingerprints: {nil, %{}},
host_uri: %URI{
authority: nil,
fragment: nil,
host: "localhost",
path: nil,
port: 4000,
query: nil,
scheme: "http",
userinfo: nil
},
id: "phx-FhTzcNm5Pubn5gdB",
parent_pid: nil,
private: %{
assign_new: {%{}, []},
connect_info: %{},
connect_params: %{
"_csrf_token" => "RB0GMy0wYhFeBwpPMHhFPB5bahlpKQUwtzekhTRFlQ3bzK6qPnYr8eDV",
"_mounts" => 0
}
},
redirected: nil,
root_pid: #PID<0.819.0>,
root_view: MyAppWeb.ShowNewsLive,
router: MyAppWeb.Router,
view: MyAppWeb.ShowNewsLive
}
[error] GenServer #PID<0.819.0> terminating
** (ArgumentError) assign @current_user not available in eex template.
I’ve blown away node_modules and mix.lock and re-installed those dependencies to no avail.
My package.json phoenix deps:
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
The bottom of my app.js:
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content");
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}});
liveSocket.connect()
What might be going wrong here?
Thanks