Improve perceived performance by predicting the future outcome
A set of utilities to achieve Optimistic UI effect. Helps to bridge the gap between async state changes.
Converting async counter to optimistic component that reacts to user actions instantly:
import React, { useState } from 'react';
+ import { useOptimisticUpdate } from "use-optimistic-update";
export default function UpTo3Counter() {
const [counter, setCounter] = useState(0);
+ const { value, onUpdate } = useOptimisticUpdate("count3r", counter);
const increment = (value) =>
new Promise((resolve) => {
setTimeout(() => {
if (value <= 3) setCounter(value);
resolve();
}, 1000);
});
return (
<button
onClick={() => {
const newValue = counter + 1;
- increment(newValue);
+ onUpdate(() => increment(newValue), newValue);
}}
>
- Likes: {counter}
+ Likes: {value}
</button>
);
}
npm i use-optimistic-update
or
yarn add use-optimistic-update
- shareable state between multiple components
- hooks
- direct event emitter access
- typescript support
useOptimisticUpdate
is a hook that let's you sync and update the optimistic state.
import { useOptimisticUpdate } from 'use-optimistic-update';
const { value, onUpdate, isUpdating } = useOptimisticUpdate(
stateKey,
realValue,
);
Options
stateKey: string
- Required
realValue: string | number | boolean | undefined
- Required
Returns
-
value: string | number | boolean | undefined
- The optimistic value
-
onUpdate: ( updater: () => Promise<void>, newValue: string | number | boolean | undefined, ) => Promise<void>;
- Updater function that should be called when you want to update real and optimistic values
updater
- Async function that should perform the real value change
- While this function is executing the optimistic value is perceived
newValue
- The new optimistic value
-
isUpdating: boolean
- Is an update being performed for given
stateKey
- Is an update being performed for given
<button
className={}
onClick={() => {
onUpdate(async () => {
await incrementCounter();
}, counter + 1);
}}
>
{counter}
</button>
useOptimisticState
is a hook that let's you retrieve the optimistic state.
import { useOptimisticState } from 'use-optimistic-update';
const { value, isUpdating } = useOptimisticState(stateKey);
Options
stateKey: string
- Required
Returns
value: string | number | boolean | undefined
- The optimistic value
isUpdating: boolean
- Is an update being performed for given
stateKey
- Is an update being performed for given
optimist
is the underlying event emitter used by the hooks. It is responsible
for updating / syncing of optimistic / real values.
Synchronize the real value with optimist
instance.
import { optimist } from 'use-optimistic-update';
optimist.sync(stateKey, realValue);
Options
stateKey: string
- Required
realValue: string | number | boolean | undefined
- Required
Update optimistic value inside the optimist
instance.
import { optimist } from 'use-optimistic-update';
optimist.update(stateKey, updater, optimisticValue);
Options
stateKey: string
- Required
updater: () => Promise<void>
- Required
optimisticValue: string | number | boolean | undefined
- Required
import { optimist } from 'use-optimistic-update';
optimist.update(
'count3r',
async () => {
await incrementCounter();
},
counter + 1,
);
Retrieve the optimistic state.
import { optimist } from 'use-optimistic-update';
const { value, isUpdating } = optimist.getState(stateKey);
Options
stateKey: string
- Required
Returns
value: string | number | boolean | undefined
- The optimistic value
isUpdating: boolean
- Is an update being performed for given
stateKey
- Is an update being performed for given
Retrieve the optimistic state.
import { optimist } from 'use-optimistic-update';
const unbind = optimist.onUpdate(stateKey, listener);
Options
-
stateKey: string
- Required
-
listener: ({ value: string | number | boolean | undefined; isUpdating: boolean; }) => void
- Required
- The function that will be called every time the optimistic state changes
Returns
unbind: () => void
- A function to remove the event listener
import { useEffect } from 'react';
import { optimist } from 'use-optimistic-update';
useEffect(() => {
const unbind = optimist.onUpdate('count3r', ({ value, isUpdating }) => {
console.log('count3r changes:', value, isUpdating);
});
return unbind;
}, []);
- What is Optimistic UI?
Optimistic UI is a pattern that you can use to simulate the results of a mutation and update the UI even before receiving a response from the server.
MIT