Suggestions on hook impovement - custom useOptimistic
Unanswered
Vojin posted this in #help-forum
VojinOP
Hi! I don't really wanna play around with experimental features since there will be a lot of maintenance with it, I want something that simply works. Now this works for my use case and I think it can prove to be useful, but can't stop thinking that there could be a bug somewhere. If you have time, I'd appreciate you taking a look at the code below:
usage:
export function useOptimisticState<T>(initial: T) {
const [state, setState] = useState(initial);
const [optimistic, setOptimistic] = useState(initial);
const updateState = async (
optimisticValue: (prev: T) => T,
trueValue: (prev: T) => Promise<T>
) => {
setOptimistic((prev) => optimisticValue(prev));
trueValue(state)
.then((data) => {
setState(data);
})
.catch((e) => {
console.log(e);
setOptimistic(state);
});
};
return [optimistic, updateState] as const;
}
usage:
const [profileOptions, setProfileOptions] = useOptimisticState({
isFriend: profileData.isFriend,
friendRequestSent: profileData.friendRequestSent,
notificationsOn: true,
});
const handleFriendRequest = async () => {
setProfileOptions(
(prev) => ({ ...prev, friendRequestSent: "ok" }),
async (prev) => {
const res = await sendFriendRequest(profileData.id);
if (res.data) return { ...prev, friendRequestSent: res.data.id };
throw Error(res.error);
}
);
}
3 Replies
White-winged Scoter
I tweaked it a little bit
So you can use it the same way you would use a regular useState aswel
export function useOptimisticState<T>(initialValue: T) {
const [value, setValue] = React.useState<T>(initialValue)
const [optimistic, setOptimistic] = React.useState<T>(initialValue)
const updateState = React.useCallback(
async (
optimisticValue: React.SetStateAction<T>,
trueValue?: (prev: T) => Promise<T | undefined>,
) => {
setOptimistic(optimisticValue)
try {
const data = (await trueValue?.(value)) ?? optimisticValue
setValue(data)
setOptimistic(data)
return data
} catch (error) {
setOptimistic(value)
}
},
[value],
)
return [optimistic, updateState] as const
}
So you can use it the same way you would use a regular useState aswel
Also added the setOptimistic in the response (maybe it has an updates ID or something else that changed server-side. And that's the source of truth most likely)
VojinOP
This looks great, thanks, I prefer the args structure the way I wrote them (it's been used a lot since the last post hence the decision), but yours is objectively better, thanks