Better implementation of automated optimistic updates
When I implemented optimistic updates on my mutation functions, I found it difficult to reuse the common parts. And I had to implement it through the API
withOptimisticUpdate
. I'm using React & Next.js8 Replies
I very much hope to have a simple API, similar to:
onOptimisticUpdate
or offOptimisticUpdate
to make it easier for me to implement some automation control logic on the front end. Any better suggestions?
Or can I define an optimistic update function in the convex backend first, and then call it through a hook in the front end?I hear you on it being difficult to build a catalog of optimistic update functions. Could you say more about what you want instead? If you want to know when the update has succeeded, the promise returned from the mutation may help (is that what
offOptimisticUpdate
would do?)
You can define the optimistic update anywhere (re: "in the convex backend first" but it's code that runs on the client. Are you saying you'd like to define it next to the definition?Something we've considered is defining the optimistic updates as tied to a mutation, not a call to a mutation.
Along the lines of:
Would something like this work for you and make this better or not?
I was thinking if we can design the optimistic update such that we can just enable / disable it with a boolean variable as most of the time there is no conflict resolution, for example we can just automatically find all the queries that may be impacted by the mutation and inject the local storage piece of the code for it?
is this something that is possible to be implemented?
The challenge is that each query could be fetching a different subset of results and combining them in different ways, and it’s unclear how to cleanly combine local results with a new or modified value. If you normalized your values and stored them all in a unified store client-side, you could do some things automatically, but that would be a subset of what’s supported by Convex
I am not sure, I imagine the atomic mutation can be propagated to whatever queries that was using them (just like how the reactivity is implemented in convex, but in a local copy of it), if you have all the mutation, queries and db connected as a graph the propagation logic will be clearer (mutation -> db -> query), and such helper function can be built in compile time, and it will be used when I call
useMutation('...').withOptimisticUpdate()
, this would cover most optimistic update cases unless it requires CRDT like conflict resolutionOne hitch is your mutations & queries could be reading & writing to documents that are never surfaced to the client (and in some cases are intentionally not on the client), and generally not all records that influence the return of a query are available on the client at the time the mutation executes, so it's generally not possible to replay the server logic there. You also generally don't want to ship your server logic to the client if it's using env variables or other secret info. So I believe the design space for the fully-automated optimistic updates is limited to CRUD-style / normalized stores. Does that make sense / am I understanding your proposal right?
I understand your concern now, maybe we can figure out a way to get away from these corner cases? Or maybe in the parameters of
withOptimisticUpdates
, we can select which queries can be synced in a local first manner automatically and warn users what might be the consequences of it (if I used a secret in an query most likely that involves some external fetch which makes it impossible to mock in the frontend anyways)