How do you achieve Optimistic UI in Phoenix with LiveView?

LiveView now adds some classes, such as phx-click-loading, whenever you do an action. This can be used to provide some UI feedback and in many cases. For more complex cases like the chat example, then you need to fallback to JS with phx hooks.

6 Likes

Another approach, probably best implemented within LiveView itself, is to preemptively evaluate and send the changes that would result if the action where taken. Assuming that the code that generates the template is pure with no side effects (or can be parameterized to disable side effect code), then the renderer could ā€œfollowā€ actions such as click events and include that diff along with the current payload. This best supports actions that result in a limited number of determinist outcomes. The tree of possible actions is probably prohibitively large or even infinite so configuring an allowed number of traversals and allowing for explicit overrides of actions/branches might be necessary.

Of course, having elixir run in the browser is even better…

Also curious how people are approaching this. I’m new to Elixir and Phoenix so it’d be great to see examples of best practices.

I saw Jose’s OpenAI optimistic ui example that handled the delete use case.

I haven’t tried it yet, but I suppose insert / update would be possible with hooks or possibly JS commands.

For example, I think an insert would have to use hooks. I think it’d require manipulating the DOM on submit and adding an element for the new item. I’m not sure how LiveView would handle the rollback in case the insert fails on the server. Maybe it would ā€œjust workā€ :slightly_smiling_face:.

An update might be able to use JS commands if it’s something simple like toggling a checkbox, e.g. marking a todo complete.

1 Like

Toggling a checkbox in a form doesn’t really need any help does it? It toggles as soon as you click it.

I’d say it’s less important for updates and inserts than it is for deletes. What I like to do is ensure the inputs to add an extra thing are already rendered (visible or hidden), so when someone clicks the ā€œadd another oneā€ button it doesn’t take a trip to the server to show the form.

Those ā€œwent to the server for a UI change when it could have been done with a JS command or hookā€ interactions are the sort that you really notice on lazily implemented LiveView sites.

IMO the more JS and hooks you add, you get exponentially less benefit in time from using liveview.

Liveview’s design philosophy is to have the server control the state of the page, this makes things 100x times easier to reason about. Of course the latency is the biggest enemy here, but I would always advise to resort to client-side state as last resort, not as the initial implementation.

1 Like

Sure, managing state in two places is a recipe for disaster. But that’s not what I’m suggesting.

Trying to avoid writing any JavaScript is another way to create a subpar user experience. Buddha says that we should follow the middle path when it comes to server and client interactivity and I tend to agree.

3 Likes

While I generally agree with this, I also think that a lot of things we take as standards these days, like for example that UI should be always responsive in some manner just don’t make much sense for some projects.

I used liveview for admin panels for almost all of my projects. There, I don’t care about user latency, even though that can be a problem sometimes if you have huge payloads (which happens more often than I expected at first). You want a fully reliable system that is fully synchronized with what actually happens on the server, and the complexity running a configuration server is usually insane, so adding the additional layer of client-side state is just unwise in such situations.

We have to fully understand where it makes sense to add additional features, otherwise I think the trip to server liveview offers by default is superior to any hacks involving client-side state modifications.