-
Notifications
You must be signed in to change notification settings - Fork 959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Removing and adding same item in stream doesn't sometimes keeps the old state of inner live components #3664
Comments
I tried to trigger the bug in older versions of LV to see when it was introduced and I went back until 0.20.0, and I still could trigger it. This made me think that maybe this is some kind of optimization instead of a bug. Even if that is the case, this optimization seems to create a bunch of issues with hooks. For example, in my case I have a hook that will draw a chart, I use a function in the component |
@sezaru I think there's not much we can do to change this, as it's a consequence of how LiveComponents work. Basically, the LV protocol relies on the client to tell the server when a LiveComponent is removed from the page:
Now, let's assume a latency of 500ms (single trip) and look at how this would look like:
This is needed to fix race conditions. It also means that if you add the component back between step 1 and 5, which needs two round trips, the LiveComponent will not be destroyed on the server:
If you need to ensure that you get a new LiveComponent, the only way is to roll the ID that you give the LiveComponent: @@ -66,7 +66,7 @@
<div id="items_stream" phx-update="stream">
<div :for={{dom_id, %{id: id}} <- @streams.items} id={dom_id}>
- <MyComponent.live_render id={id} />
+ <MyComponent.live_render id={"#{id}-#{System.unique_integer()}"} original_id={id} />
</div>
</div>
"""
@@ -105,9 +105,9 @@
def render(assigns) do
~H"""
- <div id={@id}>
+ <div id={@original_id}>
{@blibs}
- <MySecondComponent.live_render id={"#{@id}_second"} />
+ <MySecondComponent.live_render id={"#{@original_id}_second"} />
</div>
"""
end |
Oh and thank you very much for including the reproduction. I appreciate your effort very much! |
Environment
Actual behavior
Consider that you have a stream in your LV and you have an item inside of it.
That item renders a LiveComponent. If I add some latency to the call
liveSocket.enableLatencySim(1000)
and I remove the item and then, around half a second after I re-add it, the live componentupdate
function will be called with the state of the removed component already insidesocket.assigns
.Also, if that same live component has another live component inside of it, its
update
function will not be called at all.Here is a code that reproduces the bug:
I recorded a small video showing the issue:
first_video.mp4
As you can see, when I remove the item, I wait around half a second after it disapers from the DOM and then I click to re-add it again. In the terminal, it says "GOT THE BUG!" from the first component, you can also see that
blibs: 1
is inside the socket assigns even thought it should be empty, and I also don't get any message from the second component (because itsupdate
function is never called).Expected behavior
Since I first removed the item from the stream and then I re-added it again, it should re-add the component with an empty state, not using the older one.
Here is a video showing the expected behavior, in this case I waited around 2 seconds to click in the re-add button again to not trigger the bug.
second_video.mp4
The text was updated successfully, but these errors were encountered: