Should I use setState inside useEffect with React Query (or TRPC)?
Lets say I want to fetch a product and set the result to a zustand store.
Since tkdodo mentions we shouldn't be using onSuccess (it will be deprecated fully soon), is the only approach to just add:
Is there a better way to approach this?
TkDodo article:
https://tkdodo.eu/blog/breaking-react-querys-api-on-purpose
Breaking React Query's API on purpose
Why good API design matters, even if it means breaking existing APIs in the face of resistance.
29 Replies
There’s no need to store it in separate state - you’ve already got the value in productData
Also do yourself a favour and don’t destructure the result of useQuery/useMjtation
Thank you @brendonovich , the main reason I store it in a different state is because that state has a ton of actions that can ultimately modify it before we ultimately use a mutation to update a bunch of records on our DB.
So in my client, I need to store the data in a particular way that allows me to modify it via different actions in my App, then ultimately use that final modified data to save it.
Essentially need to fetch data, transform it and hydrate my Zustand store. The Zustand store contains many actions such as deleting particular pieces of that data.
Ahh basically for an edit form, that makes sense
Yeah for sure if I just needed to read the same data I'd just call the same useQuery since the fetched value is stored in cache
Is the useEffect for when the data loads or for when the selected id changes?
the useEffect should be for when the data loads. In my example I hard coded a '5' but in my actual app that would be a variable as you mention.
So ideally if the id changes, the useQuery fetches the new value and the new value is set via the useEffect
Hmm, useEffect does work but I think I'd implement it a bit differently, something along the lines of giving the form a
key
and using Suspense
to wait for the data to be loaded
Though storing the product in zustand does kind of mess with that
Might be worth spreading the product data into a new object when you assign it though, unless you're already doing that in zustandYeah that would sounds good but I'm sure big enough apps need to hydrate some sort of store if they have a lot of logic/modifications going on within the client
Yeah in zustand the setter I use only accepts that product and hydrates wherever I need the product to be stored
I'm curious what sort of modifications you need to do? I'd just hook all of the product data up to React Hook Form and let it take care of everything for me
I'm using Formik actually
And I just wouldn't render the form until the product had loaded
But should be similar
Nice, yeah maybe the overall way I'm setting up the data is kind of flawed
Oh interesting - Formik with an external zustand store?
I'll give you the actual example:
I'm building a customer transaction page for a shop that sells wooden sheets / planks.
When I first visit the page, I am fetching the base transaction info (such as customer name and order number....) and I am also fetching all the transaction line items. To easily find which transaction line item I want to edit, in Zustand I setup a Map where the key is the line item number and the value is the all information that makes up that line item.
So when I click on the line item, I can quickly load the selected line item information.
Hmm, I wonder if you'd have a better time using the vanilla trpc client inside your actions instead of using the react query integration
Since you're basically trying to synchronise 2 separate stores and the react lifecycle
yeah basically at any time we have the actual server state, and the state of the form on the client (prior to the user saving).
Just found this, going to give a read through the comments see if someone has something similar too https://github.com/TanStack/query/discussions/5279
GitHub
RFC: remove callbacks from useQuery · TanStack query · Discussion #...
I wanted to write an RFC, but after I announced it on twitter, I decided to make a blogpost. This should cover most of the questions around that topic: https://tkdodo.eu/blog/breaking-react-querys-...
@brendonovich do you have any examples of how you're handling fetching data for forms before ultimately updating and saving to the server?
i've got a whole application for ya haha
it's a lil messy but here's one
https://github.com/spacedriveapp/spacedrive/blob/main/interface/app/%24libraryId/settings/library/locations/%24id.tsx
GitHub
spacedrive/interface/app/$libraryId/settings/library/locations/$id....
Spacedrive is an open source cross-platform file explorer, powered by a virtual distributed filesystem written in Rust. - spacedrive/interface/app/$libraryId/settings/library/locations/$id.tsx at m...
Thanks! Taking a look!
One thing that is concerning about using suspense though is from
https://tanstack.com/query/v4/docs/react/guides/suspense
says not to use in prod 😦
Suspense | TanStack Query Docs
NOTE: Suspense mode for React Query is experimental, same as Suspense for data fetching itself. These APIs WILL change and should not be used in production unless you lock both your React and React Query versions to patch-level versions that are compatible with each other.
React Query can also be used with React's new Suspense for Data Fetching...
oh well, i like it
Yeah it's pretty neat
alternative is to just do the data fetch in
Component
and conditionally render the formYeah there's a few options, overall for my example, I think I need to rethink how I'm even handling all the data to begin with. Might have to rethink the overall Zustand store
Yeeeah mixing multiple solutions for storing server state gets dicey
Ultimately reread the original article and found that we shouldn't really by state syncing using both react query and something like redux (or zustand) so for now this would be the way even though it sucks