T
TanStack•3y ago
magic-amber

Is it ok to use setQueryData to edit query state instead of useState?

Hello, I have a react component where I am editing stripe product in my database. Instead of adding useEffect and useState in my component to handle the state, I thought why not just use setQuery method instead. Is it okay to handle all edits with setQueryData method, meaning creating different handler functions such as handleAddNewProductFeature, handleDeleteProductFeature, editFeatureDescription and so on.
const handleAddNewFeature = () => {
if (!productQueryData) return;
const newFeatures = [
...productQueryData.product_id.features!, // I am expecting products to be created with at least empty array
{
feature_description: '',
order_number: productQueryData.product_id.features
? productQueryData.product_id.features.length + 1
: 1
}
];
queryClient.setQueryData(['product', id], {
...productQueryData,
product_id: {
...productQueryData.product_id,
features: newFeatures
}
});
};
const handleAddNewFeature = () => {
if (!productQueryData) return;
const newFeatures = [
...productQueryData.product_id.features!, // I am expecting products to be created with at least empty array
{
feature_description: '',
order_number: productQueryData.product_id.features
? productQueryData.product_id.features.length + 1
: 1
}
];
queryClient.setQueryData(['product', id], {
...productQueryData,
product_id: {
...productQueryData.product_id,
features: newFeatures
}
});
};
I don't want to mutate any state in my database, unless I know that user is happy with changess and press save button, only then I persist those changes to my database. Is it common to have this approach?
No description
5 Replies
wee-brown
wee-brown•3y ago
The risk with this approach is to have the updated data erased when the query does a refetch . For example, the query would refetch the data when it's manually invalidated or a new observer is mounted (another component calls useQuery with the same keys) or the browser window is re-focused (unless disabled in the settings) etc... In such cases, the fresh data received from the api would replace the data you manually updated in the cache. To mitigate this you would either have to tweak the settings to make sure the query is never refetched unless specifically triggered (but you would lose a lot of the benefits and this could easily get overlooked in future updates) or maybe use the structuralSharing option in order to merge your updates in the "fresh" data (haven't really used it so not sure it's appropriate for this). For such cases, I would probably store the updates in a separate state and merge those with the data returned by useQuery.
magic-amber
magic-amberOP•3y ago
So if I need that data globally, I would store the editable state with something like redux?
wee-brown
wee-brown•3y ago
redux, jotai, zustand, there are many great options out there 🙂 that's my take btw, I'd be curious to hear what tanstack maintainers would recommend for this case 🙂
magic-amber
magic-amberOP•3y ago
For sure, im curious as well!
like-gold
like-gold•3y ago
I wouldn't suggest using the query cache for mutation draft states. It can be invalidated and lost when you might not expect it to. I'd suggest local state via useState/useReducer that you then perform a mutation with and optimistically/pessimistically update the cache.

Did you find this page helpful?