You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Following our chat yesterday I ended up attempting to write a custom hook that would work just like normal state but also sync updates with the DB in the background. It seems to work reasonably well, and is hopefully not too confusing 😅
I think using something like this would probably be easier at this stage that trying to work in a whole new library/paradigm (i.e. React Query).
Here's how you'd use it:
functionApp(){// need to pass in two fns: to load initial state and to update it laterconst[state,setState]=useRemoteState({ load, update });if(state.status==="loading")return<div>Initialising...</div>;if(state.status==="error")return<div>Something went wrong!</div>;constcount=state.data.count;return(<main><p>{count}</p><buttononClick={()=>// simple update:// setState({ count: count + 1 })// or pass a fn to update based on previous state (just like normal React state):setState((prev)=>{return{count: prev.count+1};})}// updates are blocked while previous one is pending// but for good UX indicate to the user that button won't workdisabled={state.status==="updating"}>
Click me {state.status==="updating" ? "..." : "+"}</button></main>);}functionload(){// TODO: actually fetch data from DB// has to return a promise resolving with the initial data// e.g. supabase.table("thing").select("blah");}functionupdate(changedData){// TODO: update the right bit of the DB using the `changedData` object// just has to return a promise (resolved value isn't used)}
I'm gonna describe exactly how it works in detail, which makes it seem super complicated 😅. But really the idea is you use it pretty much like useState({}), and just don't worry about all the DB syncing happening in the background.
Basically you give the hook two functions that return promises: load and update. It will call load and use the eventual result as the initial data (state.data).
It returns an array of two things, just like useState. The first is a state object like this:
conststate={status: "loading"||"updating"||"success"||"fail",data: null||{your: "data returned from load"},error: null||newError(),};
and the second is an updater function. This is a little more convenient than useState's, because it will shallow-merge updates. E.g. if your data is: { count: 0, other: "thing" } then calling setState({ count: 5 }) will result in { count: 5, other: "thing" }.
Calling setState immediately updates the local state (so the user sees the changes instantly), but also calls the update function you passed into the hook and waits for the promise to resolve. This is known as an "optimistic update".
While this is happening state.status will be "updating", so you can show an indicator to the user that data is syncing in the background. While updating the hook will prevent further state updates (to avoid e.g. setState({ count: 1 }) taking longer than setState({ count: 2}) and ending up showing 2 locally but having 1 in the DB).
The text was updated successfully, but these errors were encountered:
Following our chat yesterday I ended up attempting to write a custom hook that would work just like normal state but also sync updates with the DB in the background. It seems to work reasonably well, and is hopefully not too confusing 😅
I think using something like this would probably be easier at this stage that trying to work in a whole new library/paradigm (i.e. React Query).
Here's how you'd use it:
I'm gonna describe exactly how it works in detail, which makes it seem super complicated 😅. But really the idea is you use it pretty much like
useState({})
, and just don't worry about all the DB syncing happening in the background.Basically you give the hook two functions that return promises:
load
andupdate
. It will callload
and use the eventual result as the initial data (state.data
).It returns an array of two things, just like
useState
. The first is a state object like this:and the second is an updater function. This is a little more convenient than
useState
's, because it will shallow-merge updates. E.g. if your data is:{ count: 0, other: "thing" }
then callingsetState({ count: 5 })
will result in{ count: 5, other: "thing" }
.Calling
setState
immediately updates the local state (so the user sees the changes instantly), but also calls theupdate
function you passed into the hook and waits for the promise to resolve. This is known as an "optimistic update".While this is happening
state.status
will be"updating"
, so you can show an indicator to the user that data is syncing in the background. While updating the hook will prevent further state updates (to avoid e.g.setState({ count: 1 })
taking longer thansetState({ count: 2})
and ending up showing2
locally but having1
in the DB).The text was updated successfully, but these errors were encountered: