Much appreciated. I started implementing React Query on top of Zustand and started to think, why this sounds like duplicating data. Great and simple explanation.
as an entry level developer, with no work experience, i got that part at the very begining when i tryed tanstack query. i guess now i can be proud! :D great channel btw
Спасибо большое за великолепный урок. Я долго искал реализацию этой задачи, что бы просто было. И вы объяснили как нельзя лучше. Видно, что у вас огромный опыт. Успехов каналу в развитии.
Be careful with calling zustand this way. To properly "tree-shake" it you need to go with const data = useStore((state) => state.data), not just const { data } = useStore(). Anyway great video!
Great video! However, instead of managing the filters using client state, I suggest using URL parameters. This approach helps in sharing URLs with specific filter settings, making it easier for users to bookmark or share filtered views.
Awesome tutorial. I rarely get to watch ones that are oriented towards real projects and touch on architecturing your application using the target tools and aiming to establish best practices.
Splitting the state into client and server adds another level of complexity for the component itself. Now your component has to differentiate between the two types, and it basically binds the two state types which imo is also a weird pattern. One can argue that the filter params are also a "server" state because that's how your server knows which data to return! And you see how it can be a point for argumentation within teams. Instead, what I'd do is decide to come up with the single "data" state which overlooks everything "under the hood" and exposes the data to the component, so the component itself can be less confusing and be cleaner. So in this example, Zustand can be a single point of reference for the component with its hooks, while the React Query can be encapsulated inside of Zustand's implementation. This way the component is really a presentational view component that doesn't know about "server" and "client". The result is a simpler code: Component
Thanks for sharing! However, I am confused here. What if I need user information to be accessed over the whole project? I would choose to call user API in the layout when the user logged in and store the information in Zustand, so that every component can access user info. Therefore I optionally chose the "wrong way" mentioned in the video, calling API by tanstack query and storing the user info in Zustand, Does anyone have a better efficient way in this case?
on the website the example they have is they make 2 types, one describing state and the other type describing actions then create the store saying create. It might be overkill but I thought it helped make the code a little easier to read. Especially if their are more than one actions assigned to a state.
Thanks the explanation. Just one questions, let's suppose we're registering a user, does the user data input be considered a client state? And Can I use Zustand to cache them?
I have to say this is true for normal cases like you described. For some other cases, you must put the users to zustand by useEffect and make changes for client. For example, in the user list, you need display an active column with checkbox, and you can check/uncheck the checkbox then submit the changes. Imagine that you have more other fields need do the same. In these cases, you have to put the users to zustand firstly by useEffect, there is no good way to implement this with react query only.
@@cosdensolutions well you can have a try, like i said, if you have multiple fields need to be updated by clients and the list also have sorting and filtering functionalities. you will see the issue. To save it in the store, you can keep the list as single source of truth. Make your life much easier.
I think the two solutions proposed in this video are trying to solve different problems. The first solution, storing users directly in zustand, is often used (for me at least) when you need to make “data” from react query globally accessible. The second solution is simply trying to add extra filtering states in addition to users and pass them to the backend API.
Yeah, I am actually dealing with the same problem right now, and am wondering if this is the right way to handle global data with react query using zustand
yeah he didn't made the data available globally but i think that you can just fetch the data again anywhere u need, as longs as the query key is the same, it will retrieve from the cache and it will like share the same data across those components fetching only once, because if the key is cached it won't fetch again
thanks for this info, it would be great to have a better demo using several server components and client components "use client"/"use server" etc... that way we can see the flow and possible errors
I think there is still some use cases to store data in store. For example, when I try to share data between different screens. In your second method, there is no way to share the data. Am I right?
I liked the explanation, really crisp! However, my only concern is this that in case let's say this is supposed to be a shared global state within a big app. Let's say you're planning to store user's profile data or auth for a simpler example. Having a zustand store, from which you can retrieve the state value in any other component feels like a much more better approach, rather than adding react-query everywhere. Would love to know other opinions and thoughts?
I like these types of video, that way I can send it instead of having to spend the time to actually explain best practices, before explaining key concepts. If you haven't done, can you also create a similar video but using query params instead of local state? Maybe also RSC patterns combined with client side code.
Have one question, tanStack query will store data in cache. But what if I want to get data from server instead of cache since the data may change at any time?
I am actually building a react native application and need help with managing state with firebase and the client app (native app) I wanna know if I can use this pattern?
What to do incase, The server data I need requires in multiple components, Should I call the query in each of those components, or get it initially in some main component and store it in zustand?
@@cosdensolutionsWhat if I need to fetch the initial data with react query and then make some complex updates and use those data on multiple components? How to deal with this?
Hi Darius, so for example, I am doing a CRUD function on that user. Basically, I update it and delete it, the initial state needs to be updated correspondingly. Do you think storing the users would be a good idea and just filter that data and change its updated object fields or remove it if it is being deleted? If no, what would be the best approach for this? TIA.
When you update or delete a user using a mutation, the best approach is to revalidate the list on success to fetch the latest details. If there’s an error, show it to the user. This way, you don’t have to manually update or filter the local state, and the data stays consistent with the backend.
Isn't it a better practice to do the "filter state management" via the URL? That way it remains persistent when refreshing the page, and when sharing the URL
actually there is Mantine React table and Material UI table that implement tanstack table very nicely and work well with react query. Also there is great documentation and examples. You would not need Zustand in the first step. Regarding the table if you want to preserve the filters, sorting and so on while the user navigates pages, that's when you need to think about how to preserve the state of the table, which may be desired or not.
make a custom hook that use react query to fetch data and pass it to tantack table and using zustand for holding state that hook return the table and loading state
How about a derived state from server state ? Let's say I got users from the backend, but I want to keyBy it and use it in multiple components. What's the best way here please ?
You could use useMemo to create a derived array/object as you want, that way you save an extra render than if you use useEffect. Or you add the logic in the fetch fn
i don't think your example is good for client state. for filtering, sorting, product variant options search param (in url) better choice then saving it in client state. Let me know if i am wrong
@@latinrev3822 pagination? Rewrite url maybe? You can use useState for that. There is no point to use global state if your state gonna be used in just 1 component
You might probably want the search params as a default/initial value, not as a state value, since waiting for the url/search params to change might hinder your UI Component, for example controling a Switch Input active state. You still need client states for a better UI transition/active state.
I think you are right but maybe he merely wanted to show the point that we should not use client globle state management like zustand to store data from server when we already use react-query or swr to handle the server data management, although the case is not that proper.
Use Zustand for anything related to UI like theme, colors, settings, etc. Use TSQuery for all your server state, I.e. data that comes from fetch calls to a backend, like a posts api that returns all posts in a social media app
Hey I have a question. Actually I felt in a situation where I make a post request to an APIs end points and I want to used the data from without passing in a zustant state. With a get request is very simple but I could not figure it out when making a post request
@@stanzy237 you can store those inputs in state and then define your mechanism for removing it. Also, you could return the input data / database output in your post response from the api and use it as well. But if you need to persist the posted data between renders or various interactions, then you will need to store it intermittently in Zustand
You don't explain what the problem is that the "naive" way tries to solve. Yes, its redundant data but unless a dev is trying to solve a particular problem by introducing zustand, I don't believe people are actually doing this. Is anyone actually doing that and why?
What's the point of setting data from an API into another store? You lose the main purpose of RQ... RQ provides a 'global store' for your data under the guise of a cache. Such videos numb people
Sorry to say, but ihonestly dislike this video. You say there are two ways 'a good way' and a 'bad way' but those two cases are totally different. I totally agree there's no point in storing the readonly, server side data into zustand. But it's usually the case that you do it, because you fetch some data, go to some edit mdoe and then you edit it on the client before sending it back as a mutation back to the server. What then? The 'bad way' becomes a 'good way' all of the sudden?
Much appreciated. I started implementing React Query on top of Zustand and started to think, why this sounds like duplicating data. Great and simple explanation.
as an entry level developer, with no work experience, i got that part at the very begining when i tryed tanstack query. i guess now i can be proud! :D great channel btw
Спасибо большое за великолепный урок. Я долго искал реализацию этой задачи, что бы просто было. И вы объяснили как нельзя лучше. Видно, что у вас огромный опыт. Успехов каналу в развитии.
Be careful with calling zustand this way. To properly "tree-shake" it you need to go with const data = useStore((state) => state.data), not just const { data } = useStore().
Anyway great video!
Great video! However, instead of managing the filters using client state, I suggest using URL parameters. This approach helps in sharing URLs with specific filter settings, making it easier for users to bookmark or share filtered views.
Awesome tutorial. I rarely get to watch ones that are oriented towards real projects and touch on architecturing your application using the target tools and aiming to establish best practices.
Can't wait for the next video: Combining Redux with Zustand and React Query
смешно смешно 😂
Bundle size: 1GB 😂
Wow, that's exactly what i was doing, but you make it even more clear! Thanks!
Splitting the state into client and server adds another level of complexity for the component itself. Now your component has to differentiate between the two types, and it basically binds the two state types which imo is also a weird pattern.
One can argue that the filter params are also a "server" state because that's how your server knows which data to return! And you see how it can be a point for argumentation within teams.
Instead, what I'd do is decide to come up with the single "data" state which overlooks everything "under the hood" and exposes the data to the component, so the component itself can be less confusing and be cleaner.
So in this example, Zustand can be a single point of reference for the component with its hooks, while the React Query can be encapsulated inside of Zustand's implementation.
This way the component is really a presentational view component that doesn't know about "server" and "client". The result is a simpler code:
Component
i like that approach but could you provide an example?
Hahah ! That video came out on point ! Thank you so much ! :)
Man im just building this now. Are you stalking me? :D Great content!
This is what I've been looking 😊 thank you
Thanks for sharing! However, I am confused here. What if I need user information to be accessed over the whole project? I would choose to call user API in the layout when the user logged in and store the information in Zustand, so that every component can access user info. Therefore I optionally chose the "wrong way" mentioned in the video, calling API by tanstack query and storing the user info in Zustand, Does anyone have a better efficient way in this case?
I think you can call the react query function in multiple components. It don't make extra request usually using cache data
and what if we need state mutations in the data , dont we need to keep the client state for that ??
on the website the example they have is they make 2 types, one describing state and the other type describing actions then create the store saying create. It might be overkill but I thought it helped make the code a little easier to read. Especially if their are more than one actions assigned to a state.
The useEffect would be necessary if these data needed to be more global. In this example you just display them in the same component.
its not necessary, data can just be fetched again from other components, and its fine since its cached
thanks for these videos for frontend development.
I guess I am the first watching this video 😅
What if i want user data in more components ?
Thanks the explanation. Just one questions, let's suppose we're registering a user, does the user data input be considered a client state? And Can I use Zustand to cache them?
I have to say this is true for normal cases like you described. For some other cases, you must put the users to zustand by useEffect and make changes for client. For example, in the user list, you need display an active column with checkbox, and you can check/uncheck the checkbox then submit the changes. Imagine that you have more other fields need do the same. In these cases, you have to put the users to zustand firstly by useEffect, there is no good way to implement this with react query only.
You could just store the IDs of the selected users in Zustand and then check against that for the UI. No need to duplicate the users
@@cosdensolutions well you can have a try, like i said, if you have multiple fields need to be updated by clients and the list also have sorting and filtering functionalities. you will see the issue. To save it in the store, you can keep the list as single source of truth. Make your life much easier.
@@geforcesong tanstackw query is for state management , you don't need to make a duplicate state. just store selectionId, filter state in zustand
Great explanation, thank you for the clarification between the client and server state management!
I think the two solutions proposed in this video are trying to solve different problems. The first solution, storing users directly in zustand, is often used (for me at least) when you need to make “data” from react query globally accessible. The second solution is simply trying to add extra filtering states in addition to users and pass them to the backend API.
Yeah, I am actually dealing with the same problem right now, and am wondering if this is the right way to handle global data with react query using zustand
You can just call the RQ hook from anywhere though, right? If the provider wraps all your components. So it's already globally accessible.
yeah he didn't made the data available globally but i think that you can just fetch the data again anywhere u need, as longs as the query key is the same, it will retrieve from the cache and it will like share the same data across those components fetching only once, because if the key is cached it won't fetch again
How have you done this beautiful cursor animation?
thanks for this info, it would be great to have a better demo using several server components and client components "use client"/"use server" etc... that way we can see the flow and possible errors
What if we need the user data in another component?
You can use useState and prop drilling or call rquery with the cache Keys yoy can get the data from cache instead of the servee
What if I want to implement filtering on the client.
I just so happen to find out about zustand
Began using reacy query a while back
And boom i find this video 5h after posting lets go
Same bro😂. Zustand then react query and got recommendations for supabase
Hello, Could you please tell what plugin allows you to have the autocompletion code ? it looks really smart to know exactly what you want to code
copilot
@@ketankumar5689 thanks
I think there is still some use cases to store data in store. For example, when I try to share data between different screens. In your second method, there is no way to share the data. Am I right?
You can access data from cache using queryClient.
@@Its-InderjeetSinghGill But it's not reliable to access from cache. So I think saving in the store is still one of the best way to pass the data.
I liked the explanation, really crisp! However, my only concern is this that in case let's say this is supposed to be a shared global state within a big app. Let's say you're planning to store user's profile data or auth for a simpler example. Having a zustand store, from which you can retrieve the state value in any other component feels like a much more better approach, rather than adding react-query everywhere. Would love to know other opinions and thoughts?
React Query is meant to call the same query in many components, they highly recommend it! That's why the cache is there and it works great
You can wrap the react query call in a helper hook that you use around your app. Then you don’t need to repeat the cache key etc
Great 👍 @@havokgames8297
I like these types of video, that way I can send it instead of having to spend the time to actually explain best practices, before explaining key concepts. If you haven't done, can you also create a similar video but using query params instead of local state? Maybe also RSC patterns combined with client side code.
«Hoo-goh shtee-glitz» ©️ TSOO-shtang
onSuccess its deprecated on newer versions of tanstack query but you can use select to transform the data and (optionally) set it on the zustand state
Great Video! But I do want to ask what should we do if need to fetch the data that we got with react query globally? Thank!
Have one question, tanStack query will store data in cache. But what if I want to get data from server instead of cache since the data may change at any time?
good question , in next js we have revalidate but i dont know about this
and also i got one doubt related to this video : what if we need state mutations in the data , dont we need to keep the client state for that ??
check docs, staleTime and gcTime are your friends
Why check data in useEffect? Why do you check data into onSuccess function of ReactQuery?
are there any disadvantages if i use useQuery and axios together?
Not at all! I do it all the time
I am actually building a react native application and need help with managing state with firebase and the client app (native app) I wanna know if I can use this pattern?
Boy do you take time to make a point...
What to do incase, The server data I need requires in multiple components, Should I call the query in each of those components, or get it initially in some main component and store it in zustand?
Call the query in each component! That's what RQ is built for. It will fetch it once then return from the cache every time
@@cosdensolutionsWhat if I need to fetch the initial data with react query and then make some complex updates and use those data on multiple components? How to deal with this?
Custom Hook @@thomasgian3223
Can we update the state with mutation
Hi Darius, so for example, I am doing a CRUD function on that user. Basically, I update it and delete it, the initial state needs to be updated correspondingly. Do you think storing the users would be a good idea and just filter that data and change its updated object fields or remove it if it is being deleted? If no, what would be the best approach for this? TIA.
When you update or delete a user using a mutation, the best approach is to revalidate the list on success to fetch the latest details. If there’s an error, show it to the user. This way, you don’t have to manually update or filter the local state, and the data stays consistent with the backend.
does anyone know why react-query removed the onSuccess property in usequery?
Its useMutation that has onSuccess
since it would causes many problems, cons are bigger than pros
There is an explanation on tkdodo's blog as to why they removed the onSuccess from useQuery
practical knowledge thank you
Isn't it a better practice to do the "filter state management" via the URL? That way it remains persistent when refreshing the page, and when sharing the URL
yes it is, making a video on that soon
I do exatly this proposal to my team past week rsrsrs
Isn't it a much better practice to do the "filter state management" via the URL? That way it stays persistent when refreshing, and sharing the URL
THANKS
Can we have a video on react query, tanstack table and zustand to make a datatable?
actually there is Mantine React table and Material UI table that implement tanstack table very nicely and work well with react query. Also there is great documentation and examples.
You would not need Zustand in the first step. Regarding the table if you want to preserve the filters, sorting and so on while the user navigates pages, that's when you need to think about how to preserve the state of the table, which may be desired or not.
make a custom hook that use react query to fetch data and pass it to tantack table and using zustand for holding state that hook return the table and loading state
Just look into Shadcn data table it uses tanstack table
thanks!!! ❤
How about a derived state from server state ? Let's say I got users from the backend, but I want to keyBy it and use it in multiple components. What's the best way here please ?
You could use useMemo to create a derived array/object as you want, that way you save an extra render than if you use useEffect. Or you add the logic in the fetch fn
Where to use useMemo, I couldn't get it ?
i don't think your example is good for client state. for filtering, sorting, product variant options search param (in url) better choice then saving it in client state. Let me know if i am wrong
How are you're going to save your filtering state to pass it to the url? you need client state to save these filters.
If you use the URL then you don't need Zustand. But not everything needs to always go in the URL
@@latinrev3822 pagination? Rewrite url maybe? You can use useState for that. There is no point to use global state if your state gonna be used in just 1 component
You might probably want the search params as a default/initial value, not as a state value, since waiting for the url/search params to change might hinder your UI Component, for example controling a Switch Input active state.
You still need client states for a better UI transition/active state.
I think you are right but maybe he merely wanted to show the point that we should not use client globle state management like zustand to store data from server when we already use react-query or swr to handle the server data management, although the case is not that proper.
guys if I use mobx do I even need react query or would it be better if I just make my queries in mobx methods
no, I would then stick to that
thank you
Is this the same for SWR?
probably yes
please do a video on redux toolkit and react Query
Use Zustand for anything related to UI like theme, colors, settings, etc.
Use TSQuery for all your server state, I.e. data that comes from fetch calls to a backend, like a posts api that returns all posts in a social media app
Hey I have a question.
Actually I felt in a situation where I make a post request to an APIs end points and I want to used the data from without passing in a zustant state. With a get request is very simple but I could not figure it out when making a post request
@@stanzy237 you can store those inputs in state and then define your mechanism for removing it. Also, you could return the input data / database output in your post response from the api and use it as well.
But if you need to persist the posted data between renders or various interactions, then you will need to store it intermittently in Zustand
@@TannerBarcelos ok great advice thank you.
But does it make sense to use the store to save user data if i need the user data to be persistent through mmkv?
Yes, and then you'd pass it as initial data to RQ
@@cosdensolutions oh yess that’s actually great…never thought of it that way.
A lot of yapping IMO. I feel zustand has specific cases but to be used for filtering is not so good. Just stick it in the url.
I learned zero things from this vid, maybe negative if we include storing filters in other place instead of url
Darius ! I know you are completely fluente in French 😄🇫🇷
Noiccceee
los videos se hacen completos, desde cero o sino no haces nada
You don't explain what the problem is that the "naive" way tries to solve. Yes, its redundant data but unless a dev is trying to solve a particular problem by introducing zustand, I don't believe people are actually doing this. Is anyone actually doing that and why?
Jotai is better and less complex
you're using them "alongside", and not really "together".
What's the point of setting data from an API into another store? You lose the main purpose of RQ... RQ provides a 'global store' for your data under the guise of a cache. Such videos numb people
Sorry to say, but ihonestly dislike this video. You say there are two ways 'a good way' and a 'bad way' but those two cases are totally different. I totally agree there's no point in storing the readonly, server side data into zustand. But it's usually the case that you do it, because you fetch some data, go to some edit mdoe and then you edit it on the client before sending it back as a mutation back to the server. What then? The 'bad way' becomes a 'good way' all of the sudden?
Zustand is "global" state management
Nice video, but it could easily have been 5 mins shorter