lostpebble / pullstate

Simple state stores using immer and React hooks - re-use parts of your state by pulling it anywhere you like!

Home Page:https://lostpebble.github.io/pullstate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Optimistic UI with async?

xaralis opened this issue · comments

Hi, I was wondering what is the best way to implement optimistic UI async actions. E.g. when the action is initiated, UI updates immediately simulating a success and optionally reverts back in case the action in fact ends up with an error.

What is the suggested way to implement this? Looking at the postActionHook, it's only called once action finishes. For optimistic UI, we need something to be called as soon as the action is started.

Thanks for this neat little library.

That's an interesting use case.

The thing about Pullstate is that it gives you a lot of rope to do what you want with it. It should be flexible enough for these kinds of situations- though that's not to say something couldn't be built into it to make this kind of thing easier still.

Currently, how I might do something like this:

Do the optimistic update directly before calling the action.run() and have a post action hook (or take a look at the result returned from run()) to then decide to roll back those changes or not.

Optimistic changes provide a whole extra bundle of challenges.. such as- what if the user runs two updates? And one of them fails? How do you roll back only that one?

But if you are doing them in the way I saw in your app- where these updates are "contained" inside an extra modal / editing screen- then I think this kind of thing could be done. You would just have to prevent the user from entering that editing screen again until the change has been confirmed (the action has returned successfully or negatively).

I'd suggest, perhaps, a technique I used to turn stateless messaging into addressable requests.

If you wrap a promise, giving it a guid for identification, you can then drop it into a pool & time them out independently of their success/failure (think of them as http requests you can cancel/timeout.)

IOW, if you use these promises guids as references you could then request one from the state - asking for/subscribing to, it's status to use within your UI -- you could define 'happy' as 'expecting success', 'satisfied' as resolved, and 'failed' as rejected.

TL;DR ? end-of-story : I was re-implementing a linux kiosk. The old code ran on a system with a touch screen. Using XWindows we put an instance of Google Chrome on the touchscreen, and served the webapp it used from Apache running on the same system. The old code used cgi-bin & was a problem for me, based on the new requirements. I needed something that could act more like a micro-services backend, slid in under a cgi-bin behavior model. (one request, response only goes to the requestor.) Given that messaging systems are not respond-to-request by nature, they are one-way publish often w/nothing more than an ack. Responses are just subscriptions, the payload has to connect them to the request. I chose, in this case because there were no other kinds of communication required, to build my mqtt-client which gives request-timeout-response behavior to MQTT messaging. So I wrapped the whole process. Each request is wrapped as the payload and given a GUID as a return address. each micro service will post their result to /reply/ -- Each request subscribes to this path, with a timeout to reject itself. Inbound subscriptions searched the pool for the guids and resolved them if they found them. (I used external promise resolution to make it work, references are in the code.) Later we were able to wrap that MQTT traffic in a RabbitMQ plugin & route the communications to-from the DBMS server, other servers, or the local system as needed.

It may help you to build off of this idea. I'd be interested if you create something...

Cheers!

Al;

https://github.com/ajoslin103/mqtt-client