Is there a way to preserve records between initial mount and connected mount in LiveView?


I am loading some records in my LiveView over an API call to an external service. In LIveView I assign these records to assigns and then, when WebSocket client connects from the browser, LiveView does a second rendering that triggers the same records to be loaded over the network again.

This not only executes the query to fetch records from external API twice, but also results in my users noticing a change on the screen between the original rendering of the page and the sequential connected mount/render, as these records do tend to change pretty rapidly.

I could solve the problem using a cache, either on the HTTP client or directly in my Elixir code, but I am just wondering if there has been a pattern developed that I am missing here, because it must be a common problem?

You can use connected?/1 to fetch records only after the socket is connected and to even better results use assign_async/3 (liveview 0.20.0 or higher) to handle the loading of the external resource.

1 Like

So I can do something like an empty page / placeholders on the initial render, or a “loading…” and then fill in the space with actual data once I got it, yes.

Hmm, might not be the worst idea ever in this particular case as I don’t need the SEO benefits of server-rendered pages here at all.

Yeah, if you want SEO and avoid refetching using a cache would be the best option, but since the BEAM simplifies a lot of stuff that you need various services in other stacks, a “dumb” cache that fetch the resource in !connected?/1, store in :ets and then retrieve (and clear) it in the connected?/1 should not take more than 10 or so lines.

(Just be careful, live navigation does not mount the first request when connected?/1 is false).