tomekowal
The topic of optimistic UIs in LiveView came up already e.g. How do you achieve Optimistic UI in Phoenix with LiveView? by @pillaiindu
but I wanted to show my solution.
LiveView team claims that LV is not suitable for optimistic UIs but I feel that there is a conceptually easy fix for that I present in this repo: GitHub - tomekowal/optimistic_counter: An experiment with optimistic UIs in Phoenix LiveView · GitHub
I described my solution in the optimistic_counter/README.md at master · tomekowal/optimistic_counter · GitHub
Let me know what you think about it!
Trending in Discussions
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
New
Hey there,
It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Quite interesting article Google brought me. Didn’t find any mentions about it here.
What do you think in general? Would you use togethe...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
Since we have deprecated our Erlang sections (as we have dedicated Erlang Forums now) let’s add this thread for those who’d like to post ...
New
:warning: Security advisory: Decimal DoS vulnerability
A vulnerability has been published for decimal where very large exponents can cau...
New
Other Trending Topics
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
Aludel - LLM Evaluation Workbench
Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Exadra37
One recommendation:
Try out whatever you are trying to do in a commuting trip, like by train, bus or even as passenger in a car and then see if Live View fits the use case, because it will not if used to every DOM change, it will be sluggish.
In my product I am using Live View but keeping it to places where business logic needs to be applied to, anything else is not the best fit for Live View. User interactions with the DOM are best left to be handled in the client side.
Qqwy
I think it is a great solution. I think that (simplified or full) vector-clocks might provide for a good way to resolve ‘stale’ front-ends.
One problem this approach (currently) has of course, is that the ‘optimistic’ handler needs to be written in plain JavaScript. This might change once Lumen can be used easily, or maybe one could purpose ElixirScript for it. Then again, the parts of a UI that need to be optimistic are probably limited, so it might still be possible to do the bulk in Elixir-on-the-server anyway.
tomekowal
Yep, that is my concern too.
a) I need to write JS
b) it works only for state + event → new_state transformations (if there is something impure like DB call in handle_event then of course JS part can’t do it
Implementing the logic twice in two languages is error-prone. Maybe some kind of macro that brings the JS and Elixir implementations close to each other can at least make it easier to edit both at the same time.
On the other hand, multiplayer games are perfect examples of doing exactly that. The same logic is repeated in client and server. Server is the source of truth.
LostKobrakai
For such cases I’d currently rather look into node ssr for client and server side rendering of those components and try to couple it with a channels solution, which might work similar to liveview in the process spawning / callbacks, but skips all the complexity of the templating / template diffing.
tomekowal
Thanks for your input! If I understand you correctly, you propose to write the core event handling logic in JS so that you can reuse it both on the server and client and then use channels to synchronize the states.
It might work but LiveView gives me much more. The server LiveView process is a single source of truth and I loose that if I use plain channels. The state synchronization is very hard to do efficiently so I really appreciate how great LiveView is in reducing the payload size between client and server.
LiveView also gives me entire lifecycle in case of dropped connections. Doing all that using channels seems like a big hurdle that would end up in a half reimplementation of LiveView.
I might be greatly underestimating the task of adding event counters to client and server side of LiveView but after we have that, optimistic UI algorithms boils down to:
It might need a separate “client modification timestamp” for each “gap” in the template and some JS functions to set that stamp when you modify those gaps on the client side. But it still seems like much less work than building custom solutions on bare channels.
LostKobrakai
You’ll lose that as soon as your client becomes stateful for the state you also deal with on the server.
This is exactly the reason, why liveview doesn’t synchronize state at all. There’s state on the server and there’s markup derived from this state. The markup is sent to the client and replaces existing markup. There’s the fancy markup diffing, where the client does indeed hold some amount of state (the static parts), but everything on the client is replaced in the case of a reconnect.
This basically boils down to an CRDT implementation. There’s e.g. automerge for JS, which implements crdts for json data and also has existing tooling for synchronising data via network connections. The “problem” for an elixir based solution is that you need node on the server or you need to re-implement the automerge crdt protocol in elixir. I’ve experimented with automerge from client to client proxied through phoenix channels in the past and it’s interesting tech, but also complex.
josevalim
FWIW, LiveView already does this internally. For example, imagine you have three buttons on the page. Once you click them, they change their text to “Processing…”. Processing each button takes 1 second. If you click all 3 of them one right after the other, the first response will come in t=1, then t=2, then t=3.
if LiveView did not track the events, once t=1 arrived, all buttons would revert to their original text, but it doesn’t.
So maybe we can generalize this a bit so people can also leverage this information in hooks or similar, but the whole infrastructure is already there. This may be possible, I think it is a great idea!
Not really. The goal with optimistic UI is to change the client as a way to optimistically guess what the server will return. There is no state is really. The changes you do on the client will be discarded as soon as the ack is received.
LostKobrakai
Seems like I misunderstood the intro. Seems like counters as examples nowadays automatically mean distributed state to me
tomekowal
Haha
I might not have been clear enough 
Thanks for validation! I’ll check if I am able to dig in into infrastructure enough to propose something meaningful.
I currently imagine the API like this:
phx-hookbut I would like to tie optimistic updates to JS LV events instead of DOM lifecycle events)josevalim
I have talked to Chris about an API like this:
In a hook, you will be able to call
this.syncPushEvent(...)this.syncPushEvent(...)will block all over-the-wire updates to the Hook, until an ack to the syncPushEvent is received. Custom JS code in the hook still runs thoughOnce a reply for the push event is received, we call the hook updated callback, so you can apply the server state to the hook contents
It is basically the mechanism that we use for optimistic UIs in buttons and forms, except we are making it available for hooks too. WDYT?