As the final tutorial in the React Redux Toolkit series, this advanced lesson takes the blog project we completed with async thunks in lesson 5 and the knowledge we gained from the intro to RTK Query in lesson 6 and combines them for a complete refactor of the blog. When finished your Redux Blog will have fully integrated RTK Query with the entity adapter for normalized state (ids & entities) and you will learn how to achieve optimistic updates for an immediate UI response. If you are just getting started with Redux, I recommend going to the beginning of this React Redux Toolkit for Beginners playlist here: ru-vid.com/group/PL0Zuz27SZ-6M1J5I1w2-uZx36Qp6qhjKo
@coderNerd I'm curious about what user token you are referencing? I did not use any tokens in this tutorial. Are you thinking for a login / authentication - like JWT auth token?
@coderNerd for sure! You wouldn't necessarily need tokens for the login either - just depends on the backend design. I could look into doing a Redux Login Auth tutorial, too.
I can’t express in words how grateful I am to you, the course is at the highest level, as well as the react course on creating a blog, you are a great fellow and this content is even better in some places than many paid courses on udemy, I am sincerely glad that I got on your channel, I hope everything will be fine in your life!
Hey Dave. Loving your content. I think it would be very valuable for the community if you could create another more basic tutorial using RTK query starting with a project from scratch. I feel like I followed your redux tutorial pretty well up to this one. However, with all of the copying, pasting, and refactoring, this video was by far the hardest to follow. I have watched it multiple times now and done a bit of digging elsewhere and in the docs and am slowly getting it, but I would love a video with a more basic approach with a simple project from scratch. All the best!
Holy moly, Dave. This has got to be the toughest lesson you've put together yet! There's a heck of a lot to take in here. I get the general idea of how it all works but understanding it in detail, line by line, is really difficult.
Definitely one of the most complex topics I've covered, and this is the final advanced lesson in the series. The more you work with it, the easier it gets. Also, the MERN Stack Project series I'm completing applies all of this.
This channel is definitely one of the greatest resource for anyone who want to learn the mern stack for now😅. I know you are going to add more awesome content in other technologies as well. May Allah blesses you sir👑❤️
Splendid! What a treasure. Thank you, Dave. I wish there was just an extra example with the latest v2.0 (combine slices, lazy loading, in-slice new selectors mechanism, etc.) but overall, that series is top notch.
thankyou sir for this excellent tutorial and great explanation too. It makes my life easy with redux.. as a beginner, I'm having a hard time with redux but after this tutorial, this is changed.
I think it's confusing to have methods called like "AddReaction" when what they actually do is update the reactions with a new value passed in through the parameter, that method is being named after its expected usage but it will be confusing for other developers. Very good tutorial though.
Thanks. This one, with all the new syntax and without any visual presentaion of the outcome along the way (for 45 minutes), was a particular tough one..
I appreciate your effort in all the content you have produced. Your are truly a credit to the community. I have to admit, though, that the pace of the last few videos was difficult for me. I am sure it's due to all of these concepts being new to me, but there were a few times I felt like I was trying to drink from a fire hose. I had to step away, and come back later. I'm still a bit confused on the async / thunk approach vs. RTK Query. From my reading, it seems that the RTK Query library is meant to reduce boilerplate and be more efficient in the purely mechanical process of moving data. However, it is not diet thunk or thunk-light. I'm not sure if it was the pace or my newbness, but the concepts and verbosity of RTK Query didn't make me want to use it more than using thunks. I need to tinker with it, I suppose. I felt like the concepts in thunks were at least within my grasp of understanding, but when following along with the advanced RTK query tutorial, a lot of it was just too dense to digest. Will likely have to replace my mouse from the number of times I had to pause, back up.... but I do appreciate all you do. I'll have to spend some more time with Redux.
It is a lot to take in all at once. I also moved more quickly than I usually do because there is a lot to cover here. Give it time. Work with it awhile. Also, my new MERN series is going to use Redux and RTK Query in the frontend, so it will give you a chance to see it all in action with another full project. 🚀
Great tutorial! I have one question. How to pass argument to query build if api call is for exmaple "/users?arg=foo"? Because when Im trying to pass it from component via useSelector by calling selectUsersResult with an argument its not working. It only works when Im hardcoding argument in usersSlice like that "usersApiSlice.endpoints.getUsers.select('foo');" but in my case arg is dynamic so it cant work like that. I would appreciate help with this, thank you
Thank you for walking through this very helpful. I think the table way of thinking is effective, yet not always needed depending on scale. I will take that into my job and see if it is best for us. But thank you for being so slow and explaining absolutely everything. Helps me to make my own assumptions and thoughts that works best for my team =)
This is a fantastic tutorial however personally does not like to use redux and rtk because i still see a lot of chunks of code to be written if we work with redux. React router actions and mutations and react query makes them so easy compared to Redux.
Hi Dave, you have awesome tutorials. If it's not too much to ask, but could you make a tutorial project with Material UI or React Bootstrap Framework one that uses JS and one that uses TS?
Thank you and thank you for the requests! It's not too much to ask at all. I am planning a Typescript series that I want to complete before doing any other Typescript content. I could also do the Material UI or Bootstrap for React / JS content beforehand.
Thanks for the video, that's exactly what I was looking for! The only difference is I use redux-saga, because there's A LOT of complex asynchronous logic in my project. I am having a hard time trying to weave it into the stack you represented.
@@DaveGrayTeachesCode I do like it too! Just to clarify, I meant the scenario where you would use sagas on top of RTK Query. Imagine if after fetching posts in your example you would also need to make a couple of other requests, probably wait for some events to happen in particular order and so on. I saw that recent major release of RTK added something to compare sagas features, so you could keep using thunks, but I haven't tried it yet.
Hello Dave, Great work you are doing, one more request from me is to add a video where you show how to use all this with typescript. And one please for Next js with Redux Toolkit. It would help a lot. Thanks💛
Thank you and I appreciate the requests! I plan to do both Typescript and Next.js series later this year. I can follow those up by adding Redux to each, too. 🚀
why its called "apiSlice" ? it should be "apiReducer" cuz "createApi" returns reducer that can be passed to for example "combineReducers" or i miss something ? thanks
Thanks for the wonderful tutorial. would like to see last part preform without the Performance Techniques and Optimizations, and focusing the combinng RTK Query with Redux Toolkit. Thanks again. great job!!!
provideTag { type: 'Post', id: "LIST" } Is ' id: "LIST" ' array? it will store data to LIST array, when mutation get data from API. The array is sort by id?
Hi Dave, great video but a lot to take in! I have one question regarding line 61 at 15:50. Why do we need to pass in the selectPostsData(state) function? Why can't we just use getSelectors(state => state.posts) like we did last time? I know selectPostsData() is creating a memoized selector but I thought normalized state was kinda memoized anyways
Hi there Mr. Gray! I would really like to express my gratitude towards your work! Your Redux Toolkit - RTK Query course is truly amazing! I learned so much by watching it and reading documentation afterwards. Your tutorial significantly simplifies understanding of some tricky parts of Redux library. However I have a small question about this tutorial, if you will. So when you update a reaction in the list of posts, it looks like the whole list is being re-rendered. Is it expected behaviour or only one post should be re-rendered as it was in Redux Toolkit series? Thank you in advance!
It has been too long for me to remember the specifics without diving back in. Either way, I think you could apply what I did with the optimizations to avoid this even if I didn't at the time.
Hey Dave thanks for the series. I have a question. How can we do infinite scroll in rtk query ? As far as I research I can do it with the merge function that query provides. But I have multiple mutations and in addition I can mutate selected items with checkboxes like one item in offset 0 another in offset 100. So how can I make it refetch twice for both offsets. I can not find any information about it on the internet.
Could you make tutorial video on React testing using jest and react testing library ( testing for example redux vs redux toolkit actions reducers for comparison on how to test both)
How to pass arguments to select method, Because we are using pagination for get all endpoint. we are sending the page number dynamically, for that select method also expecting the same page number. But i dint get solution for that. can you anyone help me.
Hi Dave, great video as it's always the case with your content. I do have a quick question for you, should we use a normalized state even if the content that we need to retrieve from the API is not a list but a single element?
Hi, great tutorial! Just the question: I need to add flag like: isUsersListEnabled: true after successfull data fetch. Where and how this flag could be added?
Great video! Would love to see an addendum that walks through or compares using the automatic code generation from an open api spec that rtk query can do
I think that returning postsAdapter.setAll in the transformResponse isn't entirely correct, you'll notice the issue if you use typescript, the transformResponse should return the same type of the response, so I believe removing the return will solve a lot of trouble, correct me if I'm wrong please, because I'm facing an issue with types while using typescript
Hi Dave. Thanks a lot for this crucial series. But, I need to make a clear in my mind. In the SinglePostPage, postId comes from useParams and we get post object by the help of SelectPostById selector. In this scenario, it works because we are getting all data from api. But what if our getPosts query in the postApiSlice is pagination oriented? And what if we need to go to SinglePostPage by changing postId from search bar and that postId is not exist in state? It says "not found". I am confused how to come up with this scenario. I would make an api call if post id is not in the state. This is my solution. I wonder what your approach is? Thanks a lot again. It is amazing.
Hi Dave, only 7 minutes in, but this video looks great, thanks! Quick question - what are you thoughts on Redux recommending only one slice per project with rtk query? Obviously you're still splitting the slices here, but I was wondering if you could expand upon why please? (for example it doesn't matter/redux are worried about something that rarely occurs/you're working off older advice etc...) Love it though, thanks!
I have seen this whole series of tutorials and thank you so so much for doing this. It's amazing to find this kind of content. I just have to questions: I didn't really understand the providesTags part 😅, why the id List to each item? What is result, error and args in it? And also is not doing the same thing twice putting calling the get Post on the index. Js and also the useGetPostQuery on the Post List. Js? I hope you can help me, and once again thank you 😊
You're welcome, Oscar! That's a lot of questions to answer here. I am opening up a Discord in the next day or two that will hopefully allow for a community to help answer questions faster than I do. Let's start with at least a basic one - providesTags. That was covered in the tutorial before this one. It is referring to the cache so RTK Query knows when to invalidate previously fetched results and fetch new ones. You label what was fetched with a tag like "list" for the full list of posts or just a specific post id for an individual post. If that data is fetched again, it should invalidate the previous data stored with that tag.
Is there a way to await the api.endpoints.[apiName].initiate() that manually fetches the posts. I have an application where I need to download some data before the user sees the first screen.
This create confusion. Hello Dev, Do we have to create different apiSlice for user? I means to say apiSlice/feature or one? Can we only use Asyncthunk?
Async thunks were introduced earlier in this series, but they are used with RTK Query. If using RTK Query like this video does, you want to define your endpoints to handle everything. You can have multiple slices that all get appended back to the main slice. For example, here I am creating a slice: github.com/gitdagray/react_redux_toolkit/blob/main/08_lesson/src/features/api/apiSlice.js ...and then here I _inject endpoints_ into that slice for posts: github.com/gitdagray/react_redux_toolkit/blob/main/08_lesson/src/features/posts/postsSlice.js ...and then here I _inject endpoints into that same slice_ for users: github.com/gitdagray/react_redux_toolkit/blob/main/08_lesson/src/features/users/usersSlice.js
nice video, thank you Dave, but i have a question please, can i use createSelector for POST methods, let's say that the backend api to fetch data was POST method, i know it has to be GET, but sometimes someone else is working on the back end so you have no control
I think what you are saying is the backend API you are working with is out of your control, and you must request data with a POST method instead of a GET method request. It is not ideal, but you can do that in your slice. createSelector should not be any part of this. createSelector pulls data from your Redux store for use in a component. Instead, and especially with RTK Query, you will want to use selectFromResult with the hook that RTK generates. It will select data from the cache created by RTK Query. Look at this example of selectFromResult: github.com/gitdagray/react_redux_toolkit/blob/main/08_lesson/src/features/posts/SinglePostPage.js
i am having problem while uploading image to my node express express (multer) i am using rtk query but if i use axios then it work if anyone can guide me on this then i will i will post my gist
Is there a way to invalidate a tag without refetch immediately. My use case: add post invalidate my posts, but i do not want fetch my posts until i enter the screen of my posts
I’m not totally sure this would work but when you add a post, just make a POST request to the api sending the new post but don’t add any tags and change state or anything. The new post will be assigned a brand new tag anyways when you click on the post screen and refetch them
Ok, im trying to understand this "creaApi"...!!!... So everytime i need to share some data from "state" with few other components, ... im gonna have to fetch data again,... again ...and again ?.... if it is !!... think i prefer the "creatSlice" better, and simple to deal with ..... cause this "creatApi" is very confusing !! and imagine this on a big application where you have share data all over with other components !!! ... but anyway ...like always you tutorials are awsome... !! .. and i can't thank you enough this great content.. 😎👍
No need to fetch again and again. If you have already fetched the data, you can use the selectFromResult option. Ref: redux-toolkit.js.org/rtk-query/usage/queries#query-hook-options
You're welcome! Ajax... is an acronym for asynchronous javascript and XML. With modern JS, you want to know about async and await along with the fetch API. I have a tutorial for all of those things here: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-VmQ6dHvnKIM.html
@@DaveGrayTeachesCode I am grateful for your help. I mean this exactly. Can i focus on fetch instead Ajax.Sorry, I study js recently, and may ask bad question.
Great Tutorial Dave, I do have one question, I am getting an empty state back when using useGetPostsByUserIdQuery. It passes the isLoading condition and for the isSuccess condition it passes but I get an empty array. My logic is exactly setup like yours.. Any suggestions?
I can only guess as I did not have that issue. If you don't see a difference, you can use a tool like diffchecker.com to find any differences. You can also copy my package.json from the course resources and then run npm install to insure your dependencies match mine.
Hi Dave,I saw that example video on youtube RTK Query CRUD operation without any axios or Fetch use,and some use RTK Query with Axios/Fetch ,Would appreciate if you can tell us what is the deferent in this...approaches
I think it is just a preference for using Axios or not. Axios is not required with RTK Query, but it can be used. I did not demonstrate Axios usage with RTK, but here is the documentation for it: redux-toolkit.js.org/rtk-query/usage/customizing-queries#axios-basequery
Hi, Great tutorial. I was looking at the comments for typescript implementation. Did you get a chance to do that? I am stuck with entityAdapters getSelectors after using the RTK query!
I have not re-created this with TS, but the maintainers have said they are adding TS to the docs. I don't see it everywhere yet, but I think the goal is to have examples like you see on the following page with both TS and JS: redux-toolkit.js.org/rtk-query/api/fetchBaseQuery
@@DaveGrayTeachesCode Another question I have is, in my injectEndpoints's transformResponse, I am just returning the response without modifying it. (I am later planning to update it to modify the response). But I am not doing setAll. Even then I see that the data has been set. Why do I need setAll at all?
@@DaveGrayTeachesCode One last question. In the chapter 7, you are using store.dispatch(extendedApiSlice.endpoints.getPosts.initiate()); Based on the video, I understood that this was necessary to initiate the store when application starts. But you arent doing this in Chapter 8. Any reason?
Usually, inside the component we abort the API call and prevent local state update on unmounting the component. In case of RTK, we don't need to abort the api call as we are updating the global redux state. RIGHT?
LOVE! all the courses from js to nodejs but Redux seems super hard 🥲. I mean I get it but still it seems super complex. @dave what are your thoughts on other state management tools like Recoil/Jotai? Also, just a request, please 🤗! for the redux part in the mern tutorial could we add a refactor using context or recoil/jotai?
Thank you! Great questions and requests! I think there are a lot of great state management tools available, and I definitely want to cover more of them. A refactor of the MERN Stack Project series with a different state management library is a good idea. I was also considering doing that with React Query. 💯🚀
thanks so much for such a great tutorial, but I have a question, I am using the same code, but when I am adding a reaction on one of the posts, the posts list and all the posts are rendered again !!!
Yes, it sounds like you are using React 18 which was released after this video. Fix: change the concat in there to creating a new array with the spread operator.
@@DaveGrayTeachesCode Sir I just cloned you repo and tried, the current version is React 17, could you please check your profiler, because I am going to consider the way you implement it in our company project, and thanks again for such a great tutorial
@@DaveGrayTeachesCode Hi sir, I got the same issue and as you say above: "change the concat in there to creating a new array with the spread operator.", but we need change that at 'addReaction' endpoint or somewhere?, cuz I don't see you use the concat in your code, hope you help me soon!. Btw, your tutorials are amazing. Thanks so much, sir!
Hi Dave. I found it quite difficult to understand the interaction between providesTags and invalidatesTags. I went into docs as well, but still find it difficult to fully grasp how things exactly work. When we update or delete the post, we found this specific post since we provided it id in invalidatesTags, but does it mean that it will trigger the refetch of all posts which will update the cache state? It seems so far the hardest part to understand what and why is exactly fetching “behind the scenes” and how to construct those refetching logic with Tags. Thanks)
I understand as the things "under the hood" of something like RTKQ can be a bit confusing at first. RTKQ will refetch whatever is invalidated in the cache. Updating one post does trigger a refetch of the list as well as the individual post. Some components may be subscribed to the list while others may be subscribed to just one post at the current time. I think the docs explain it best in this section: redux.js.org/tutorials/essentials/part-8-rtk-query-advanced#invalidating-specific-items
@@DaveGrayTeachesCode thanks for your replies it helps to deepen understanding. Did I understood it correctly, that updating or deleting post will trigger the getPosts Tags as well, so all the posts will be refetched? I initially thought that it will cause to refetch all the posts by particular user/author. I am also not sure about preflight response. I thought we have only those response when reaction is clicked, but we just updated the post only. I guess it would be easier for me if I could see each providesTags and invalidatesTags array, so that I can exactly see what is going on when one is invalidated. Just can’t currently make the JSON work (issue on my side with Mack). But thanks again!
My 'getFilteredMails' endpoint like getPosts endpoint takes one argument. But in the end, although the response from the server is the result of what I want, they are not cached. (I think it is because of argument) So can you please tell me how to use when I want to use method like 'getPosts' with arguments? 😥
You can pass arguments and RTK Query still caches the response. For example, the getPostsByUserId receives an id parameter. It sounds like you are applying RTKQ to a project of your own with getFilteredMails. That said, download my source code (lesson 7) in the repository and see where yours may differ.
In many respects, yes. That said, an async thunk will work with Redux and does not require RTKQ. RTKQ uses a cache instead of your normal Redux store. I suggest using RTKQ whenever possible and only a Redux store (in the non-cache sense) where you deem necessary.
If you are following this series, the answer to your question is explained in video #5 on performance optimizations: ru-vid.com/group/PL0Zuz27SZ-6M1J5I1w2-uZx36Qp6qhjKo
Hi Dave, really nice tutorial, but I have a question. If we add a new post it appears in posts list, but when I click on user who creates this post, there is no new post in the list of user's posts. I have to manually refresh page and then new post appears to the list of user's posts. Is there a way to refetch list of user's posts when we click to user's page without refreshing the page? Sorry for my english, I hope you get what I mean :) EDIT: I just updated getPostsByUserId providedTags and is working now: providesTags: (result, error, arg) => [ ...result.ids.map((id) => ({ type: 'Post', id })), { type: 'Post', id: 'LIST' }, ],
Hi Dave, there are three conventions: selectAll: selectAll___, selectById: select___ById, selectIds: selec___Ids But what if I want to select one item from every object in the array? such as selecting only the score from an array like this: [{id: 1, score: 40}, {id: 2, score: 56}, {id: 3, score: 83}] I have tried changing the selector like this: const select___ = createSelector( select___Result, ___Result => ___Result.data.map(item => item.score) ); but it dosen't seems to work. I don't really want to destructure the array inside the component every I use it. Is there are any ways to do it in the slice?
Good question, David! There is an example of what you are asking for in the docs under createSelector: redux.js.org/tutorials/fundamentals/part-7-standard-patterns#memoizing-selectors-with-createselector ...essentially, you can create the selector you want in the slice. Here's an example of getting all of the user names: export const selectAllUserNames = createSelector( selectAllUsers, users => users.map(user => user.name) )
It doesn't replace it, but instead, it works together. RTK Query is the API layer. You might have other state to manage in Redux that does not come from the API.
Having read the documenation, I believe that your tutorial is thorough but it might be counterproductive when using it in a real application. You don't need to use all the features you added in your apis here, specially the adapter and the state selectors. Based on a conversation with a Redux maintainer, he mentioned that using adapters or modifying the data in the transform data property inside the api is ok. Maybe you should clarify that you are including two approaches, but not best practices?
I'm just covering concepts here. Take what you want from what you learn to apply to your own applications. As far as the organization of this playlist goes, as I mention early on in the series - it is based off of a tutorial in the offical docs. I think I say something like "to give credit where credit is due..." It is free. I never please everyone. I cannot go back and edit it or clarify after posting to RU-vid. Note: I have added an extra "chapter 8" that is available in the course resources that does not have an associated video. It may clean up some of what you see here. The tutorial from the docs that this is all based on: redux.js.org/tutorials/essentials/part-1-overview-concepts
I value your opinion, but disagree. I think the code is organized better with the RTK integration and API slice. It follows the official docs, but you can do organize it or rename the files as you like.
Oh it doesn't seem that's an extremely difficult app, but you are using such not understable way Nobody uses such patterns, you are not devide your code, and trying to do him so complex, that's make me feel confused
"Nobody uses such patterns"... that is incorrect. This tutorial and all the tutorials in this Redux series are based on the Redux docs. In fact, they recommend my compiled Redux course that includes this video on the Redux website: redux.js.org/tutorials/videos
sorry for bothering you Dave, but i think i found a problem when i pass arg to query i can not use create selector, for example this: ----------------------------------------------------------------------------------- const postsAdapter = createEntityAdapter({ selectId: data => { return data._id; }, }); const initialState = postsAdapter.getInitialState(); const postsApiSlice = apiSlice.injectEndpoints({ reducerPath: postsApi', endpoints: builder => ({ getPosts: builder.query({ query: arg => ({ url: 'posts', params: {...arg}, }), transformResponse: response => { const resultData = response.data; return postsAdapter.setAll(initialState, resultData); }, providesTags: (result, error, arg) => { return [ {type: 'Posts', id: 'LIST'}, ...result.ids.map(id => ({type: 'Posts', id})), ]; }, }), overrideExisting: true, }); export const {useGetPostsQuery} = postsApiSlice; export selectPosts = postsApiSlice.endpoints.getPosts.select(); const selectMemoizedPosts = createSelector(selectPosts, result => { console.log('result', result); return result.data; }); export const { selectAll: selectAllPosts, selectById: selectPostById, selectIds: selectPostIds, } = postsAdapter.getSelectors( state => selectMemoizedPosts(state) ?? initialState, ); --------------------------------------------------------------- on component i call this const {isLoading} = useGetPostsQuery(params); --------------------------------------------------------------- i don't know if this is a bug or not but selectMemoizedPosts should be fired every time the data status change, for example uninitialized, pending... so when i remove the params from useGetPostsQuery and send just useGetPostsQuery() it works fine
That's too much code to review in the YT comments. Please join my Discord server where you can post your code in an easy-to-read formatted way. You will also receive help from the community: discord.gg/neKghyefqh