Phoenix_live_view: Error CSS class applied on live redirect

Created on 24 Jun 2020  路  15Comments  路  Source: phoenixframework/phoenix_live_view

Environment

  • Elixir version (elixir -v): 1.10.2
  • Phoenix version (mix deps): 1.5.3
  • Phoenix LiveView version (mix deps): 0.13.1 and 0.13.3
  • NodeJS version (node -v): 12.15.0
  • Yarn version (yarn -v): 1.19
  • Operating system: Alpine Linux
  • Browsers you attempted to reproduce this bug on (the more the merrier): Safari, Firefox, Chrome
  • Does the problem persist after removing "assets/node_modules" and trying again? Yes/no: Yes

Actual behavior

When attempting to patch a view, the socket channel is closed causing LiveView to apply the phx-disconnected and phx-error classes.

Enabling debugging on the LV socket, the console indicates:

phx-FhtH3uxH1TwGEAGC destroyed: the child has been removed from the parent -  undefined
....snip.....
FhtH3472VSTUkwcB error: view crashed

This behavior can be replicated on the chirp repo when deleting a new "tweet".

Expected behavior

Channel remains open or the close/open is seamless not causing the phx-error class to be attached.

needs more info

Most helpful comment

We should not set the phx-error class on live_redirect, only phx-disconnected. I can confirm that we set both, so will take a look first thing tomorrow!

All 15 comments

Can you provide a full stack trace from the server logs? Thanks!

Also, please try LiveView master, as we fixed some bugs lately. Remember to remove assets/node_modules and install again after pointing to master.

Can you provide a full stack trace from the server logs? Thanks!

There are no meaningful server logs as there's no actual crash/error on the server. This _seems_ to be entirely specific to the frontend.

Also, please try LiveView master, as we fixed some bugs lately. Remember to remove assets/node_modules and install again after pointing to master.

Sorry, I failed to mention I did try master and also applied both yarn install --force and blew away node_modules.

I should also mention that we didn't notice this issue until after we upgraded to 0.13.0, which I did notice this commit changed the channel connection/error behavior.

I cannot recreate referring the post related LV in your repo. Can you describe exact steps to reproduce and include the server logs? (even the regular ones if you have no stacktrace). For example, you say it fails when you "patch", but are you referring to live_patch closing the "New Tweet" modal, or actually deleting a newly created tweet? In either case it looks good on my side so more info would be helpful. Thanks!

Are you sure you don't have "Preserve logs" checked on the client web console and you're seeing the crash message from the "New Post" redirect? Also note that your delete code is incomplete. Your UI won't respond properly to re-assigning the :posts assign to fetch_posts() because your container is always going to append content. You need to do something like this:

  def mount(_params, _session, socket) do
    if connected?(socket), do: Timeline.subscribe()
-   {:ok, assign(socket, :posts, fetch_posts()), temporary_assigns: [posts: []]}
+   {:ok, assign(socket, posts: fetch_posts(), posts_id: 0), temporary_assigns: [posts: []]}
  end

  def handle_event("delete", %{"id" => id}, socket) do
    post = Timeline.get_post!(id)
    {:ok, _} = Timeline.delete_post(post)

-   {:noreply, assign(socket, :posts, fetch_posts()}
+   {:noreply, assign(socket, posts: fetch_posts(), posts_id: socket.assigns.posts_id + 1)}
  end

and in your index.html.leex:

-<div id="posts" phx-update="prepend">
+<div id="posts-<%= @posts_id %>" phx-update="prepend">

It sounds very likely that your web console logs from the previous "page" are confusing the issue. That said, I don't see any phx error classes that persist across the page so it's possible something else is going on on your side.

My apologies, the chirp repo is not one I created or maintain; it was a recent LiveView example repo that I pulled down to test to see if I could replicate an issue we are experiencing in our own project.

After trying to replicate the issue I noticed earlier, I now see what's happening. It appears to be a stale view issue. If you create 2 tweets, then attempt to delete those 2 tweets, it won't remove the last one until you click delete a second time, which _is_ what triggers the JS error and causes the view to crash and then reload on the frontend.

I believe I have conflated two different issues. Our issue is specific to a live_patch attempting to update a view (changing actions in the same LiveView).

What we are seeing when attempting to patch a new view is immediately on user agent click, the XHR request fires off successfully obtaining the template to patch, but immediately after that the channel is closed and the phx-disconnect and phx-error CSS classes are applied to the LV container; the view then reloads with the correct action shown.

If it would not be for special styling we apply to that state it would be a rather seamless action unbeknownst to the user, but given that we attempt to indicate to the user some sort of connectivity error giving the .phx-disconnect .phx-error state, there's a 1-2 second moment of this state. This also happens when the user agent presses the back button; many of our LiveViews will have this disconnect/error state briefly applied.

Can you put together a minimal example that reproduces your issue? The chirp one we can consider resolved as the 2nd delete click crashes the server because the query will fail to find the deleted record.

I will try and create a repo that replicates the issue within the next day. But I do have a question about:

but are you referring to live_patch closing the "New Tweet" modal

Is this behavior expected? When this action occurs, is the brief setting of those disconnect/error classes expected?

Ah I see the actual issue now. It may have made sense in the past for us to set the disconnected class, but now that we emit page loading events it does not make sense to treat a patch as disconnected for styling. Note that live_redirect will indeed set disconnected classes since the LiveView is no longer active. pox-disconnected on its own is benign feedback, but you can pair with phx-error to style a crashed recovery scenario. Thanks!

Thank you Chris! Sorry for the initial poor description.

No worries. Let me know if master gets you rolling properly :)

* phoenix_live_view 0.13.3 (https://github.com/phoenixframework/phoenix_live_view.git) (mix)
  locked at 9367cb0

Just gave master a try (and I did clear out node_modules), patch appears to be 馃憤

Note that live_redirect will indeed set disconnected classes since the LiveView is no longer active.

This makes sense, but not something I had really thought much about. Just to confirm, when redirecting from a LiveView, it's expected that the disconnect and error styles are applied?

The crux here is more stylistic. Behavior all works, but as stated earlier, we do style based on the phx-error and it's a very jarring user experience to see a big red modal pop up asking the user to refresh the page, especially when it's only for a split second.

We should not set the phx-error class on live_redirect, only phx-disconnected. I can confirm that we set both, so will take a look first thing tomorrow!

Thanks again @chrismccord for addressing this so quickly! Just tried https://github.com/phoenixframework/phoenix_live_view/commit/695213dd4053343e305c7e03d849393751f80a88 and confirmed it fixed things for us. Cheers!

Was this page helpful?
0 / 5 - 0 ratings