Hi! I have a decent amount of work experience with Elixir, but mainly on an API, so no direct experience with LV yet, aside from some experimenting.
I have on my hands a Laravel+Inertia project that needs to be rewritten and I’d like to migrate to Elixir. I know Inertia is available for Phoenix too, but I’m trying to understand if LiveView can work for this use-case.
The TLDR is:
- is LV a good choice for an app that has some interactivity, but does not require frequent or live updates?
- assuming frequent disconnects, is there any resource on how to provide a good UX? I could not find any.
Now some more details
The target audience is largely going to connect from their smartphone. The main page of this app has some interactions with live search and filters, a resulting infinite scroll list for loaded data, and small interactions here and there though buttons on each item that open pop-ups with extra details, loaded when the pop-up opens. Nothing special. There’s more but this is the relevant bit for my questions.
Disconnects are, at least in my area, somewhat frequent. Think entering into a store and having low signal. This is very much relevant since this app let’s you search info about products and is likely to be used in that exact scenario.
There is enough to navigate but not enough for a stable, uninterrupted, websocket connection.
This causes LV to rebuild it’s server side state on reconnect, and in some cases it could happen every 20-30 seconds. Reconnects also happen when reopening the browser from the background, at least on iOS. Other reasons could be deployments of new versions of the app.
I’m working on a demo and solved some of the problems by taking inspiration from this blog post: https://fly.io/phoenix-files/restore-liveview-state-on-startup/ and adapting it to my use-case. It works (ish) but this still produces unwanted flashes/reloads for the user.
I’ll give an example: the infinite scroll list. It seems quite difficult to get the current page to reload while keeping the scroll position intact.
What I have a hook that saves the current page on scroll. This is sent on reconnect, and only that page is reloaded so that the user at least starts from the correct page.
However this still produces a jump since the exact scroll position relative to the page is lost and a flash is visible for the data being reloaded. I’m mitigating with an AsyncResult so that there’s at least a clean transition, but there is still a transition from “list of elements → loading → same list of elements”. With disconnects this frequent, a large amount of time is also spent on reloading the exact same data. I don’t mind an extra query but the user should not have to see loading states for something that is already loaded on the page.
This is not a critique, I’m 100% sure it’s a skill issue. I feel like I’m fighting the framework and that generally means I’m doing something wrong, but I couldn’t find any up to date examples or documentation on how to accomplish this and it seems I can’t quite get there on my own.
This brings me to the second item on my list: . None of this is really “live”, as in a live stock graph would be, or a live editor with multiple users would be.
Whatever has been loaded on the page is already an ok state and LV replaces a frontend+API situation.
I’ve been trying (and failing ) to work around this by seeing if I could completely ignore a reconnect re-render, and just use the LV connection to send-receive responses like HTTP would.
This seems intuitively wrong (and not possible) as I see that LV re-renders on state changes (similar to React), but if the LiveView process holds the state and if it dies with a disconnect than the state has to be re-built and it could be completely different from before (not in this case, but conceptually). So I thought I could try to cache the state in a way that survives a disconnect, either by keeping a local copy on the client or somewhere on the server like an ETS table.
This shows some promise and I have a super basic version working, but this seems complex and while it solves the getting the correct data problem, it does not solve the showing loading states while reloading the same information problem.
Again, this is not a critique, I’m sure it’s a skill issue on my part. It just that these seem like fairly common use-cases and I’d like to learn how to properly implement them in LiveView.
If not I’m perfectly happy to keep using Inertia and plain old controllers, but LV is kinda cool and fun to use so I’d love to be able to make it work.