Thanks for your work, Mr. Gray! Im building out front end for one of my bootcamp projects and this is hugely helpful in navigating complex RTK environment!
Thanks very much for the video. I'm slowing watching and learning everything you show here. I benefitted greatly from your video. I understand much better now. I have a side question, I find the vertical line marking the block and also the horizontal line on the first line of the block very useful in following your video. May I know what extension or settings that enable this ? Thanks !!!
Awesome stuff! As usual ... quick question, do you think we should include Axios since we have RTK query? Does the RTK query handle caching and everything on its own? I'd appreciate a reply since I'm learning the whole thing from you and there is no better tutorial available on the topic anywhere ... thanx in advance!
Thanks a lot for this fantastic explanation of Redux, Dave Gray. Would you please provide some guidance on the following bug: I keep getting every post rendered twice + 2 children with the same key red error.. unable to figure out how to fix this... many thanks))
Yes, this is due to the new nature of React 18 strict mode. It only uses strict mode in dev mode. You can remove it OR you can replace the concat() call in this code and instead, create a new array with the spread operator.
This series is the most exhaustive Redux tutorial on youtube, thank you so much Dave. There are a few observations that I've had while following and I thought I might share them, at 28:15 inside the onSavePostClicked method the catch block in this case won't work because the unwrap method itself doesn't throw an error, we need to have an async function with await to achieve that functionality. Furthermore at, 5:59 and inside the fetchPosts thunk, inside the catch we are returning err.message; however, this won't work because we need to return a promise from the thunk callback and according to the promise result thunk will create and trigger the appropriate actions. Since this is not a promise thunk doesn't know what to do and it can't create and trigger the reject promise action. These are some of my observations. All in all, 'I'm really loving this series.
Good discussion! 1) The unwrap method can throw an error. See ( redux.js.org/tutorials/essentials/part-5-async-logic#checking-thunk-results-in-components ) for the same code and a further docs reference here: ( redux-toolkit.js.org/api/createAsyncThunk#unwrapping-result-actions ) ..."The promise returned by the dispatched thunk has an unwrap property which can be called to extract the payload of a fulfilled action _or to throw either the error_ ..." 2) Correct! 💯 This correction is already annotated for the video in the description and appears at 6:22. This is also already corrected in the provided Github source code. Glad you are enjoying the series!
@@DaveGrayTeachesCode Thank you so much for responding, your reply made my day. Regarding the first point, the code in the docs, the reference of which you've shared, it has an "await" before the dispatch, but at 28:15 in the video, "await" isn't typed before dispatch, which I think is why I was having trouble catching the error.
They are similar. Our posts state has the posts, a loading state, and an error just like the custom Axios hooks structure. The extraReducers builder cases respond to the promise status returned where we set the state status. Very similar structures!
I was having problems where my API for posts was being called twice and giving me 200 posts (100 unique). I disabled strict mode and it solved the problem. I don't know if that was the main culprit or just a bandaid, but after watching this video 3 times to verify it's the only thing I could think of.
Hi Dave at 9:20, you added concat method to post array, when useEffect is called, reactStrict mode will make another GET request and the response will concat with the existing post array with new array, thus post length 200 and every post element is duplicatetd
@@DaveGrayTeachesCode Thanks Dave for your reply, I used the spread operator. Again, thanks for generous contribution in making this kind of tutorial and helping future aspiring react developer in their career.
Thank you, Dave. It seems like one thing seperates this video and this entire Redux series from perfection: The absence of Redux Saga tutorial. If it is not too late to plug in another chapter - that will be more than welcome :) (...As well as your insights about the newRedux core 5.0, React-Redux 9.0, Reselect 5.0 {which I know totally nothing of}, and Redux Thunk 3.0....)
13:40 As usual you are producing high quality content which is super awesome. Dave, I am little confuse about dependency array. Can you please explain the following point. I know the use of dependency array in useEffect but still didn't get it what is the purpose of puting dispatch in dependence array? Usually we put something in dependency array whose value change but dispatch itself is a function.
Good question, Sami. If using strict mode, you will get warnings about not including it in the console. It doesn't bother anything to be there, but I agree that it may not be necessary either. It was presented this way in the docs example I based the tutorial on, so I left it in there.
In the postsSlice.js I notice that in the fetchPosts.fulfilled addCase, concatenating the loaded posts is making the posts come back twice. Fixed it by changing the line to state.posts = loadedPosts;@@DaveGrayTeachesCode
Hi Dave! Thanks for another great tutorial! I have a question. When you created a new post, you pushed it right away to the array of posts in the state. I think you dicided to go that way because the new post has not been pushed into the database which you get all posts from. Please, correct me if I am wrong. Also, if I am right, if you send (via post method) a new post into the same database which you get all your posts from, you need to dispatch fetchAllPosts again so that the new post show up along with old posts.
In the extraReducers, the builder.addCase has an addNewPost case. If the promise is fulfilled, the state is updated there. That case responds to the addNewPost async thunk promise status.
Thank you for the great tutorial. How do we manage multiple Api calls in single component. Do we have to maintain separate loading, error and succeed variables for each of them or?
Good question. The API call is issued by the Async Thunk. If you were dispatching more than one thunk or dispatching the same thunk more than once, each thunk would handle its own API call. The extraReducers builder cases in the slice would respond to the thunks separately as well.
Yeah, I always love to see your's full of knowledgable contents videos, Thanks Dave!! and please make a series of Typescript, NextJs with Redux Toolkit.
Super useful video, thanks so much this makes it so much clearer to me how to setup the architecture around thunks and async code involved with redux states!
Thanks Dave for the great videos, I learned a lot. One question, where do you use the first parameter you pass to the createAsyncThunk() function? The 'post/fetchPosts' string. How does ReduxToolkit use it?
Great question! The docs say "A string that will be used as the prefix for the generated action types". It is how Redux identifies the action, and you can see this in Redux Devtools. If we dispatch(fetchPosts()), you will see a 'posts/fetchPosts/pending' first and then either similar with fulfilled or rejected. I hope that helps!
First parameter is a string that will be used to generate additional Redux action type constants, representing the lifecycle of an async request: For example, a type argument of 'users/requestStatus' will generate these action types: pending: 'users/requestStatus/pending' fulfilled: 'users/requestStatus/fulfilled' rejected: 'users/requestStatus/rejected'
You should describe what a Thunk is more. I had to do some additional reading, and I'm watching youtube because I don't like to read 🤣 Apart from that, excellent course again Dave!
Hello - modern Redux is Redux Toolkit. This tutorial shows the using Redux Toolkit to create async thunks. This should meet your needs. As you progress in this series, you will also learn about RTK Query.
Hi Dave! I just came from your useAxios video. I'm curious if we can use the useAxios hook with createAsyncThunk and RTK in general? Let's say we put the dispatch call inside useAxios. I really like the reusability of custom hooks. I hope you can give answer as I have just started learning Redux and RTK and would love your guidance. Thank you!
I know you can use Axios with async thunks and RTK in general. I haven't tried to use a custom useAxios hook with it. The docs have a recipe for an Axios baseQuery: redux-toolkit.js.org/rtk-query/usage/customizing-queries#axios-basequery
I was following along with the video and noticed that my store duplicated the data that comes from the api. Any idea of why this is happening? Incredible video btw
Thanks! Yes, the duplication is due to React 18 strict mode and the use of concat. This tutorial was created with React 17. Other comments on this as well. Create a new array with the spread operator instead of concat.
great content learnt alot I have a question how do you add a thunk to middleware without getting an error when I do this middleware: [thunk] I get an error
Hi Dave, yours tutorials and skills are amazing, I followed this one but for some reason I'm getting twice the posts and then getting the warning of duplicate key. I downloaded the code and copy paste all the components and still happens. I was wondering if it is about react version (react v18 and react-redux v8).
From StackOverflow: React StrictMode calls all Effects twice to make sure their cleanup/unmount handlers work as intended. You may need to change your effects accordingly, even if they have an empty dependency list and would normally not unmount before the site is closed. Note, this only happens in Strict + development mode. In a production build, effects will only be called once and when their dependencies change.
One thing worth mentioning at the end of the video is that when the new posts are added one after another, we get the following warning: Warning: Encountered two children with the same key, `101`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted - the behavior is unsupported and could change in a future version.
Note that this only occurs because the jsonplaceholder website doesn't really add the new posts. I have updated the course resources code to better handle this, but it would not be an issue if not for the jsonplaceholder site behavior.
Best tutorial on UA-cam ... but you should not use try/catch in createAsyncThunk or .addCase(fetchPosts.rejected, will never be called. Just let it throw the error: const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => { const {data} = await axios.get('/posts') return data })
Thank you for the kind words, Mohamed 🙏 and great catch! My try-catch habit got in the way here. You are correct, and I have updated the source code repos. 💯🚀
Great video thanks. Still I think when looking in our own application with custom (simple in my opinion) implemenation of Redux (actions in one folder and reducers in one folder), where we are now thinking refactoring to Redux Toolkit, the whole createSlice() syntax seem to quickly get messy and hard read with one huge object as parameter where properties like "reducer" and "prepare", "extraReducers" etc in turn have there curly brackets and object.....Hope you see what I mean, kind of riskt to end up in spaghetti-syntax if not being careful . Still I will look in to it as I understand Redux Toolkit will be the standard way of setting up Redux.
Hi Dave! First of all, really thanks for this amazing tutorial! :) And I followed this one, everything works well. But I have a question, When I add a bunch of new posts, that are more than two post,
I found that they all have an id of '101'. so I saw the message "Encountered two children with the same key, `101` in the console. and I also found another related problem, when I clicked the reaction buttons, the buttons' response has a problem too. Could you check these problems? How can I solve this problem? How should I change the code?
Hello Kris - you can follow the link in the description to the resources for this Redux series and view my source code for lesson 3. Compare to yours for differences.
The reactions data is an object, but I may be missing your suggestion here? Are you thinking a separate slice for reactions? That would create more code. I kept them with the posts state because they are part of the posts. In addition, I based this on the official docs example (gave credit at beginning of video) and you can reference that structure here: redux.js.org/tutorials/essentials/part-5-async-logic
@@DaveGrayTeachesCode Hey, I just meant like an object lookup like this: const reactions = { thumbsUp: 0, wow: 0, heart: 0, rocket: 0, coffee: 0, }; At the top and then whenever they are needed within the slice you can just do something like: prepare(title, body, userId) { return { payload: { id: nanoid(), title, body, userId, reactions, date: new Date().toISOString(), }, or const loadedPosts = action.payload.map((post) => { post.date = sub(new Date(), { minutes: min++ }).toISOString(); post.reactions = reactions; return post; }); Since we're using the same object in multiple places, if we want to make a change we can just make it to the first object and it will change in multiple places in the slice.
20:40 even tho the canSave looks better it's not as good as it was, since it creates another execution context, would be perfect with just title && content && userId && addRequestStatus==="idle"; :D lovely tutorial + loved the extra POST example
Thanks sir, the video is really helpful as always. 7:00 it seems when I include catch error in createasyncthunk(), fetch data is always resolved as Success. Only works by removing the catch inside createasyncthunk.
You are correct! 💯 The source code in the course resources for this lesson was updated to reflect this awhile back. See the previous comment from mohamed youssef for this video. YT has recently introduced a feature where I can note "corrections". Thank you for the reminder - I will add this now correction note now 🚀
Hi Dave, Thanks for the tutorial. I have a very sillly question. Why we are not using addNewPost.pending and addNewPost.rejected actions inside extra reducers Similary for fetchUsers we are not using the same pattern.
Hello, thank you for the great tutorial. After you called store.dispatch(fetchUsers()) in index.js, the AddPostForm component can access users state via useSelector, but when i checked the redux global state with redux devtools, there is only posts state. How came AddPostForm component access users state without it being saved in global state ?
You may want to compare your code to my course resource code for lesson 3 as the users state is being saved. In the index.js, the fetchUsers function is imported from the usersSlice and dispatched with store.dispatch(fetchUsers())
@@DaveGrayTeachesCode Awesome, really appreciate it! Btw I tried but couldnt understand, can you tell me what is the core reason for the usage of builder in RTK?
Would this redux code/structure be same once we incorporate a backend like Express js or even Firebase? For instance, I've seen API calls generally be made in a component like PostList or else in a custom hook like useFetchCollection. However in this example, we are handling such tasks in our slices, which then makes lot of the uses cases for custom hooks not really worth it anymore.
@@DaveGrayTeachesCode IS there one you prefer/recommend? Im assuming using RTK query would be preferred since it offers performance benefits. Man...redux jus tkeeps changing haha.
First of all thanks for this great tutorial. I am having a problem towards the end. When I add the payload in AddPostForm to dispatch(addNewPost({ title, body: content, userId })) I get an error that says "Expected 0 arguments, but got 1.", which is strange, because the action should expect the payload as an argument right? I did the tutorial in TypeScript to practise that, but I don't think that the problem is with that. Do you have any idea, why that is? Also when adding a new post whe should add an id at action.payload.id = nanoid(); or else if you add more than one post, they will all have an id of 101, which will cause problems.
Ok, maybe that was TypeScript after all. For anybody, who might have that problem as well, here is how I solved it: We need a payloadCreator. so when we createAsyncThunk for addNewPost, we pass in the "initialPost". This needs a structure, so I set up an interface PostToAdd { title: string; body: string; userId: number; } and then when we pass the initialPost argument, add that type "async(initialPost: PostToAdd). That solved it for me. Thanks again for the great tutorial!
good video.... but my when i fetch from api i have been fetching the same content twice some how?? what might be the possible error here? is the key in PostsExcerpt possible error here? that only happens when i use ordered post...with normal post.map() i am not fetching the multiple data
If you are using React 18 strict mode, you might experience this. There is an array.concat() in there that doubles the results with the new strict mode behavior.
Hi Dave! Thanks for great tutorial. One question. If I update react and react-redux to the current version ("react": "^18.2.0", "react-redux": "^8.0.2"), "posts/fetchPosts/fulfilled" happens twice. How to fix it?
Quick way: Remove strict mode from the index.js. Your issue only happens because the new React 18 strict mode mounts components twice. This only happens in development mode with strict mode enabled.
@@DaveGrayTeachesCode Awesome! Yeah I know, I'm currently building an application in react next.js and redux tool kit, that's why I asked. lol I've never used next.js and redux tool kit so I'm still pretty green. Just subbed and my notifications are on! Cheers
Hello Dave, i hope this meets you well, I'm having a little challenge with this chapter, when i fetch my data from the typicode API, each post appears twice, and the top post is always inactive, because, when i use a reaction button on the one on top of the similar post, the reacton count does not respond on the first post, but the reaction counts are updated for the second one and not the first one, when i add a new post, it always goes 2nd, because like i said the first post of the similar post that loads with the app when it starts, looks inactive and doesnt even repond to any clicks
Getting duplicate posts is likely due to the concat() in the store.js - This tutorial used React 17 but now, with React 18 in dev mode, each component is mounted twice. Instead of concat, create a new array with brackets and spread in the values [...values]
Thank you very much Dave for this tutorial. I have some query though. In the case, fetchPosts.fulfilled, during execution, with this line of code: state.posts = state.posts.concat(loadedPosts) the data is displayed twice hence this warning occured: "react-dom.development.js:86 Warning: Encountered two children with the same key, `1`. Keys should be unique so that...", however, if I changed state.posts = state.posts.concat(loadedPosts) into state.posts = action.payload it displayed okay but I wonder the Time ago and and Reaction also works.
Due to this tutorial was with React 17 and not React 18's double mount behavior in strict mode. Instead of concat, create a new array with the spread operator. See other comments on this.
Hi Dave, thanks for great video, in React 18 , API is calling twice so we are getting one error ' Encountered two children with the same key, ' it's not happening in React 17
It is happening in React 18 with Strict Mode enabled. The new strict mode mounts, unmounts, and then mounts components again. This will be from the useEffect in PostsList.js in this lesson. Discussing this change and others from React 18 here: ua-cam.com/video/N41B_SVdzwg/v-deo.html ...A solution is to keep moving on in this series until you eventually switch over to RTK Query that removes this type of logic from useEffect.
Nice content and teaching. Please help us how to connect it to firebase firestore and get data from firestore using redux thunk. Thanks for the tutorial it amazing
Hi Dave, thank you for a nice explanation! I tried to add this logic to my project, which worked well, the only thing is, I think you have a mistake when fetching all data. Im not sure why you use concat method there? I think you want to add new data to an empty array, but this can go wrong as it did it my case, I had duplicated data in the array. Im not sure why, but by default fetchCountries.fulfilled case runs twice and there you get the data duplicated.. Either just assign loadedData to the state without concat or you need to put an additional if statement to check for the status so it doesnt run twice.. Cheers
Hi Darya - there was no problem with the code in React 17 when this tutorial was made. You now have an issue with React 18 Strict Mode as it mounts each component twice. Your fix should work as you noted. You don't want to concat twice. I cover the React 18 strict mode change here: ua-cam.com/video/81faZzp18NM/v-deo.html
I have a question, I saw you wrote dispatch inside the useEffect() array at line 17 inside react_redux_toolkit/03_lesson/src/features/posts/PostsList.js ` useEffect(() => { if (postStatus === 'idle') { dispatch(fetchPosts()) } }, [postStatus, dispatch]) ` what does that mean? isn't dispatch a function? how React is going to know that the dispatch function was changed? it doesn't change, it fires. What If I removed that dispatch from here? what are the downsides? And thank you 😁
thank you for this great tutorial but if you run this in react 18 will get an 100 warning of two children with same key and also blogs are dublicated in page but in react 17 there is no error
@@moretimeproductions youtube always delete my comment with link .. and as Mr Dave comment react 18 render two times in strict mode and react team already propose solutions for this
I have a question, but this may be due to react 18 rather than a redux issue. I wanted to have the posts load when the component was loaded, so I moved the dispatch statement to the component itself and put the dispatch statement inside of a useEffect. However, I noticed that when I did this that now the redux action fires twice. Upon some more reading, this is because react now unmounts and remounts the component to help devs look out for remountable components when in dev mode. If I remove the React.strictMode tags, the redux action no longer fires twice. Is there a way to prevent this behavior? Or is this why in your videos you load the state upon loading the application?
Ok I found an answer to this and it would be, upon the cleanup of a component, if the promise returned from the dispatch() function is not yet fulfilled, call promise.abort() to abort the calling of the thunk, however, I feel that there has to be a better way
As recently as React 17, you would receive a warning if it wasn't. It is a function and likely does not change. With React 18 you should not receive a warning if left out.
As I refresh the page when I am in SinglePost (say /posts/5), I get error as post not found (my custom error if post not found by id). Why? Other things work fine. I can navigate to specific post as I click on visit post but refreshing this page is causing error. I tried logging out the posts in SinglePost component and it is empty
For some reason my extra reducer is not catching the error. I tested error handling and the case for rejected never gets trigger. Looking at the thunk function, I can see that it does catch the error. I'm not sure what could be wrong here. Could you advise what could be the potential issuel
@@DaveGrayTeachesCode sure, but I also comprare it to the documentation and nothing seems different. I might have added a Middleware km the rootreducer, but how would this change the hook? :O
There is a link to the course resources which includes source code in the description. On the course resources page, each chapter of this series is linked to with source code available.
I'm finishing my third app for my portofolio and this has helped me immensely. I love the way this guy explains it and the quality he brings.
Glad to hear that it helped!
what app did u make
Highly agree.🎉
Thanks for your work, Mr. Gray! Im building out front end for one of my bootcamp projects and this is hugely helpful in navigating complex RTK environment!
Very welcome!
Thanks very much for the video. I'm slowing watching and learning everything you show here. I benefitted greatly from your video. I understand much better now. I have a side question, I find the vertical line marking the block and also the horizontal line on the first line of the block very useful in following your video. May I know what extension or settings that enable this ? Thanks !!!
This is insane! How can you make something that used to be just html files into this?! I mean... It's great, but....
Awesome stuff! As usual ... quick question, do you think we should include Axios since we have RTK query? Does the RTK query handle caching and everything on its own? I'd appreciate a reply since I'm learning the whole thing from you and there is no better tutorial available on the topic anywhere ... thanx in advance!
That is my question too
Thanks a lot for this fantastic explanation of Redux, Dave Gray. Would you please provide some guidance on the following bug: I keep getting every post rendered twice + 2 children with the same key red error.. unable to figure out how to fix this... many thanks))
Yes, this is due to the new nature of React 18 strict mode. It only uses strict mode in dev mode. You can remove it OR you can replace the concat() call in this code and instead, create a new array with the spread operator.
This series is the most exhaustive Redux tutorial on youtube, thank you so much Dave. There are a few observations that I've had while following and I thought I might share them, at 28:15 inside the onSavePostClicked method the catch block in this case won't work because the unwrap method itself doesn't throw an error, we need to have an async function with await to achieve that functionality. Furthermore at, 5:59 and inside the fetchPosts thunk, inside the catch we are returning err.message; however, this won't work because we need to return a promise from the thunk callback and according to the promise result thunk will create and trigger the appropriate actions. Since this is not a promise thunk doesn't know what to do and it can't create and trigger the reject promise action. These are some of my observations. All in all, 'I'm really loving this series.
Good discussion!
1) The unwrap method can throw an error. See ( redux.js.org/tutorials/essentials/part-5-async-logic#checking-thunk-results-in-components ) for the same code and a further docs reference here: ( redux-toolkit.js.org/api/createAsyncThunk#unwrapping-result-actions ) ..."The promise returned by the dispatched thunk has an unwrap property which can be called to extract the payload of a fulfilled action _or to throw either the error_ ..."
2) Correct! 💯 This correction is already annotated for the video in the description and appears at 6:22. This is also already corrected in the provided Github source code.
Glad you are enjoying the series!
@@DaveGrayTeachesCode Thank you so much for responding, your reply made my day. Regarding the first point, the code in the docs, the reference of which you've shared, it has an "await" before the dispatch, but at 28:15 in the video, "await" isn't typed before dispatch, which I think is why I was having trouble catching the error.
@@prince5922 ah I see! Good catch!
Great tutorial Dave thanks, can't wait to see this async thunk with useAxiosPrivate hook you created in the series :)
They are similar. Our posts state has the posts, a loading state, and an error just like the custom Axios hooks structure. The extraReducers builder cases respond to the promise status returned where we set the state status. Very similar structures!
@@DaveGrayTeachesCode so you mean I can use axios interceptor inside extraReducers builder like that?
Not inside the builder case, but I did put axios inside the fetchPosts async thunk. It could be intercepted there before returning data.
I've never seen a tutorial like this. Thank you so much. Dave ☺️
You're welcome! 🙏 Glad it was helpful!
I was having problems where my API for posts was being called twice and giving me 200 posts (100 unique). I disabled strict mode and it solved the problem. I don't know if that was the main culprit or just a bandaid, but after watching this video 3 times to verify it's the only thing I could think of.
Yes, I made a video about this React 18 change: ua-cam.com/video/81faZzp18NM/v-deo.html
Hi Dave at 9:20, you added concat method to post array, when useEffect is called, reactStrict mode will make another GET request and the response will concat with the existing post array with new array, thus post length 200 and every post element is duplicatetd
You are correct. This tutorial was made with React 17 before strict mode did that. Use the spread operator to create a new array instead.
@@DaveGrayTeachesCode Thanks Dave for your reply, I used the spread operator. Again, thanks for generous contribution in making this kind of tutorial and helping future aspiring react developer in their career.
@@saquibasghar5152 Hello friend, I have the same error for duplicated posts, Could you please help me to know how you resolve it.
Problem resolved buddy Thanks a lot @DaveGrayTeachesCode , @saquibasghar5152
@saquibasghar5152
@@hozayves // state.posts = state.posts.concat(loadedPosts)
state.posts = [...loadedPosts];
Thank you, Dave.
It seems like one thing seperates this video and this entire Redux series from perfection:
The absence of Redux Saga tutorial.
If it is not too late to plug in another chapter - that will be more than welcome :)
(...As well as your insights about the newRedux core 5.0, React-Redux 9.0, Reselect 5.0 {which I know totally nothing of}, and Redux Thunk 3.0....)
13:40 As usual you are producing high quality content which is super awesome.
Dave, I am little confuse about dependency array. Can you please explain the following point.
I know the use of dependency array in useEffect but still didn't get it what is the purpose of puting dispatch in dependence array?
Usually we put something in dependency array whose value change but dispatch itself is a function.
Good question, Sami. If using strict mode, you will get warnings about not including it in the console. It doesn't bother anything to be there, but I agree that it may not be necessary either. It was presented this way in the docs example I based the tutorial on, so I left it in there.
In the postsSlice.js I notice that in the fetchPosts.fulfilled addCase, concatenating the loaded posts is making the posts come back twice. Fixed it by changing the line to state.posts = loadedPosts;@@DaveGrayTeachesCode
Thank you, Dave, your explanation gave me a more insight of async thunk
Glad it was helpful!
Thank you Sir for this great tutorial.😍😍😍😍
You're welcome!
Hi Dave! Thanks for another great tutorial! I have a question. When you created a new post, you pushed it right away to the array of posts in the state. I think you dicided to go that way because the new post has not been pushed into the database which you get all posts from. Please, correct me if I am wrong. Also, if I am right, if you send (via post method) a new post into the same database which you get all your posts from, you need to dispatch fetchAllPosts again so that the new post show up along with old posts.
In the extraReducers, the builder.addCase has an addNewPost case. If the promise is fulfilled, the state is updated there. That case responds to the addNewPost async thunk promise status.
Was impressed by the HQ of the content. Very professional!
Thank you! 🙏💯
Thank you for the great tutorial.
How do we manage multiple Api calls in single component.
Do we have to maintain separate loading, error and succeed variables for each of them or?
Good question. The API call is issued by the Async Thunk. If you were dispatching more than one thunk or dispatching the same thunk more than once, each thunk would handle its own API call. The extraReducers builder cases in the slice would respond to the thunks separately as well.
Yeah, I always love to see your's full of knowledgable contents videos, Thanks Dave!! and please make a series of Typescript, NextJs with Redux Toolkit.
You're welcome and great requests! Those are on my list!
Great video Dave, thanks a lot.
Is this the last video of Redux series?
Thank you 🙏 and no, several more to come. Busy week this week. Next one, may arrive next week.
Super useful video, thanks so much this makes it so much clearer to me how to setup the architecture around thunks and async code involved with redux states!
Glad it helped!
Great video Dave, learnt alot from this one!
Glad it was helpful!
Thanks Dave for the great videos, I learned a lot. One question, where do you use the first parameter you pass to the createAsyncThunk() function? The 'post/fetchPosts' string. How does ReduxToolkit use it?
Great question! The docs say "A string that will be used as the prefix for the generated action types". It is how Redux identifies the action, and you can see this in Redux Devtools. If we dispatch(fetchPosts()), you will see a 'posts/fetchPosts/pending' first and then either similar with fulfilled or rejected. I hope that helps!
First parameter is a string that will be used to generate additional Redux action type constants, representing the lifecycle of an async request:
For example, a type argument of 'users/requestStatus' will generate these action types:
pending: 'users/requestStatus/pending'
fulfilled: 'users/requestStatus/fulfilled'
rejected: 'users/requestStatus/rejected'
You should describe what a Thunk is more. I had to do some additional reading, and I'm watching youtube because I don't like to read 🤣 Apart from that, excellent course again Dave!
Thank you!
Great tutorial, much appreciated, and well explained. Thanks.
Thank you Dave, hope you have a video for redux saga
I don't but I have had a few requests.
I regret why I didn't see your tutorial before I wasted my one 🕜 year 😢. Thank you Mr. Dave gray 😊
Hi Dave, please can I get your opinion on this?
For a real big project which would you work with? Redux with redux thunk or Redux-toolkit?
Hello - modern Redux is Redux Toolkit. This tutorial shows the using Redux Toolkit to create async thunks. This should meet your needs. As you progress in this series, you will also learn about RTK Query.
Hi Dave! I just came from your useAxios video. I'm curious if we can use the useAxios hook with createAsyncThunk and RTK in general? Let's say we put the dispatch call inside useAxios. I really like the reusability of custom hooks. I hope you can give answer as I have just started learning Redux and RTK and would love your guidance. Thank you!
I know you can use Axios with async thunks and RTK in general. I haven't tried to use a custom useAxios hook with it. The docs have a recipe for an Axios baseQuery: redux-toolkit.js.org/rtk-query/usage/customizing-queries#axios-basequery
I was following along with the video and noticed that my store duplicated the data that comes from the api. Any idea of why this is happening? Incredible video btw
Thanks! Yes, the duplication is due to React 18 strict mode and the use of concat. This tutorial was created with React 17. Other comments on this as well. Create a new array with the spread operator instead of concat.
great content learnt alot
I have a question how do you add a thunk to middleware
without getting an error
when I do this middleware: [thunk] I get an error
Thanks Dave, For awesome playlist 🙏
Thanks!
Thank you for the support!
Hi Dave, yours tutorials and skills are amazing, I followed this one but for some reason I'm getting twice the posts and then getting the warning of duplicate key. I downloaded the code and copy paste all the components and still happens. I was wondering if it is about react version (react v18 and react-redux v8).
Thank you for the kind words, Fabian! I think it must be React 18. If you are using strict mode v18 renders twice.
Had the problem as well, I solved it by instead of .concat the state.posts with the loadedPosts just do state.posts = loadedPosts
From StackOverflow:
React StrictMode calls all Effects twice to make sure their cleanup/unmount handlers work as intended. You may need to change your effects accordingly, even if they have an empty dependency list and would normally not unmount before the site is closed.
Note, this only happens in Strict + development mode. In a production build, effects will only be called once and when their dependencies change.
For additionnal info, consult the React documentation page "Ensuring reusable state"
@@moretimeproductions I had the same problem as well for 5 days but now I solved.
Thanks a lot buddy
really easy to undestand, thank for nice explanation
You are welcome!
One thing worth mentioning at the end of the video is that when the new posts are added one after another, we get the following warning:
Warning: Encountered two children with the same key, `101`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted - the behavior is unsupported and could change in a future version.
Note that this only occurs because the jsonplaceholder website doesn't really add the new posts. I have updated the course resources code to better handle this, but it would not be an issue if not for the jsonplaceholder site behavior.
@@DaveGrayTeachesCode thanks for the reply! I'll check it out.
a very fat big like from me man, I really appreciate what you do here ? thank you
You're welcome, Hosam! 🙏
Thank you so much this was so helpful, greetings from Peru
You're very welcome! And hello to Peru! 👋
Best tutorial on UA-cam ... but you should not use try/catch in createAsyncThunk or .addCase(fetchPosts.rejected, will never be called. Just let it throw the error:
const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
const {data} = await axios.get('/posts')
return data
})
Thank you for the kind words, Mohamed 🙏 and great catch! My try-catch habit got in the way here. You are correct, and I have updated the source code repos. 💯🚀
¡Gracias!
Thank you for the support! 💯
Thank you for this clear explanation!
You are welcome!
thank you, Dave Gray. Much appreciated.
Very welcome!
Great video thanks.
Still I think when looking in our own application with custom (simple in my opinion) implemenation of Redux (actions in one folder and reducers in one folder), where we are now thinking refactoring to Redux Toolkit, the whole createSlice() syntax seem to quickly get messy and hard read with one huge object as parameter where properties like "reducer" and "prepare", "extraReducers" etc in turn have there curly brackets and object.....Hope you see what I mean, kind of riskt to end up in spaghetti-syntax if not being careful .
Still I will look in to it as I understand Redux Toolkit will be the standard way of setting up Redux.
Dude, thank you for this!
Thankyou teacher. The tutorials are very good!
Glad you like them!
Great content. Its helping me a lot to learn redux. Thanks so much.
Glad to help!
Thank you so much, I've learned a lot from these videos
Glad to hear it! 💯🚀
Man you're talking the same as Hershel Greene from the Walking Dead xD Thx for the vid! :)
I hadn't heard that comparison before! I'm nowhere near that old, but Hershel was great on that show 💯
Hi Dave!
First of all, really thanks for this amazing tutorial! :)
And I followed this one, everything works well.
But I have a question,
When I add a bunch of new posts, that are more than two post,
I found that they all have an id of '101'.
so I saw the message "Encountered two children with the same key, `101` in the console.
and I also found another related problem, when I clicked the reaction buttons, the buttons' response has a problem too.
Could you check these problems?
How can I solve this problem? How should I change the code?
Hello Kris - you can follow the link in the description to the resources for this Redux series and view my source code for lesson 3. Compare to yours for differences.
Great tutorial, Dave.
Thanks a lot
You're welcome!
thank you, this video is helpful for me
Hi Dave! Thanks for this helpful video. Can you please tell how to paginate the posts which we get after fetchPosts async thunk?
You're welcome! I have a Pagination tutorial here: ua-cam.com/video/9ZbdwL5NSuQ/v-deo.html
@@DaveGrayTeachesCode Awesome! Thank you.
A very above explanation...
Thanks, Dave! You're saving my life here... #codingBootcamp 😰
Right on!
Great tutorial! Thank you!
Welcome!
You've earned a new subscriber
Welcome aboard!
thanks for this amazing tutorial
Thanks, appreciate the excellent tutorial
Glad it was helpful!
you best teacher in the world 😁😁
Thank you for the kind words!
Great video as always but why would you not create a seperate reactions object and add that everywhere it is needed? It would dry up your code a lil!
The reactions data is an object, but I may be missing your suggestion here? Are you thinking a separate slice for reactions? That would create more code. I kept them with the posts state because they are part of the posts. In addition, I based this on the official docs example (gave credit at beginning of video) and you can reference that structure here: redux.js.org/tutorials/essentials/part-5-async-logic
@@DaveGrayTeachesCode Hey, I just meant like an object lookup like this:
const reactions = {
thumbsUp: 0,
wow: 0,
heart: 0,
rocket: 0,
coffee: 0,
};
At the top and then whenever they are needed within the slice you can just do something like:
prepare(title, body, userId) {
return {
payload: {
id: nanoid(),
title,
body,
userId,
reactions,
date: new Date().toISOString(),
},
or
const loadedPosts = action.payload.map((post) => {
post.date = sub(new Date(), { minutes: min++ }).toISOString();
post.reactions = reactions;
return post;
});
Since we're using the same object in multiple places, if we want to make a change we can just make it to the first object and it will change in multiple places in the slice.
@@TheSesameStreetGang I see what you're saying 🙏 Yes, this would work where I had to populate the data that was not really in the fake API 💯
20:40 even tho the canSave looks better it's not as good as it was, since it creates another execution context, would be perfect with just
title && content && userId && addRequestStatus==="idle";
:D lovely tutorial + loved the extra POST example
Thanks!
Thanks sir, the video is really helpful as always. 7:00 it seems when I include catch error in createasyncthunk(), fetch data is always resolved as Success. Only works by removing the catch inside createasyncthunk.
You are correct! 💯 The source code in the course resources for this lesson was updated to reflect this awhile back. See the previous comment from
mohamed youssef for this video. YT has recently introduced a feature where I can note "corrections". Thank you for the reminder - I will add this now correction note now 🚀
@@DaveGrayTeachesCode Thank you!
This video is very helpfull for me, thanks a lot!!
You are welcome!
awesome lessons, thank you
Glad you liked it!
Hi Dave, Thanks for the tutorial. I have a very sillly question. Why we are not using addNewPost.pending and addNewPost.rejected actions inside extra reducers Similary for fetchUsers we are not using the same pattern.
Hello, thank you for the great tutorial. After you called store.dispatch(fetchUsers()) in index.js, the AddPostForm component can access users state via useSelector, but when i checked the redux global state with redux devtools, there is only posts state. How came AddPostForm component access users state without it being saved in global state ?
You may want to compare your code to my course resource code for lesson 3 as the users state is being saved. In the index.js, the fetchUsers function is imported from the usersSlice and dispatched with store.dispatch(fetchUsers())
Hi great video. When you have in plan something about redux saga with slice's?
I need to get through the redux toolkit basics first 🚀
@@DaveGrayTeachesCode redux saga using fetch api data implementation
Hello Dave, awesome video.
Can we get RTK Query next?
That is coming soon! 💯🚀
@@DaveGrayTeachesCode Awesome, really appreciate it!
Btw I tried but couldnt understand, can you tell me what is the core reason for the usage of builder in RTK?
thanks you for advance react js tutorial sir
You are most welcome! 💯
Would this redux code/structure be same once we incorporate a backend like Express js or even Firebase? For instance, I've seen API calls generally be made in a component like PostList or else in a custom hook like useFetchCollection. However in this example, we are handling such tasks in our slices, which then makes lot of the uses cases for custom hooks not really worth it anymore.
This is one way to do it. If you keep going in this series, you will see an RTK Query implementation that generates its own hooks, too.
@@DaveGrayTeachesCode IS there one you prefer/recommend? Im assuming using RTK query would be preferred since it offers performance benefits. Man...redux jus tkeeps changing haha.
First of all thanks for this great tutorial.
I am having a problem towards the end. When I add the payload in AddPostForm to dispatch(addNewPost({ title, body: content, userId })) I get an error that says "Expected 0 arguments, but got 1.", which is strange, because the action should expect the payload as an argument right?
I did the tutorial in TypeScript to practise that, but I don't think that the problem is with that. Do you have any idea, why that is?
Also when adding a new post whe should add an id at action.payload.id = nanoid(); or else if you add more than one post, they will all have an id of 101, which will cause problems.
Ok, maybe that was TypeScript after all. For anybody, who might have that problem as well, here is how I solved it: We need a payloadCreator.
so when we createAsyncThunk for addNewPost, we pass in the "initialPost". This needs a structure, so I set up an
interface PostToAdd {
title: string;
body: string;
userId: number;
}
and then when we pass the initialPost argument, add that type "async(initialPost: PostToAdd).
That solved it for me.
Thanks again for the great tutorial!
@@moretimeproductions glad you worked it out! 💯
@@moretimeproductions Thanks! This worked for e as well 👍🏾
Any idea, do we need to test the createAsyncThunk separately while testing the createSlice in Redux toolkit?
This may help: stackoverflow.com/questions/67087596/jest-testing-createasyncthunk
thank you Dave you are really help me so match
You're welcome! 💯🚀
good video.... but my when i fetch from api i have been fetching the same content twice some how?? what might be the possible error here? is the key in PostsExcerpt possible error here? that only happens when i use ordered post...with normal post.map() i am not fetching the multiple data
If you are using React 18 strict mode, you might experience this. There is an array.concat() in there that doubles the results with the new strict mode behavior.
Great content really impressive thanks a lot🙏
You're welcome!
Awesome tutorial
Glad you liked it, Sona! 💯
@@DaveGrayTeachesCode You are welcome thank you
Hi Dave! Thanks for great tutorial. One question.
If I update react and react-redux to the current version ("react": "^18.2.0", "react-redux": "^8.0.2"), "posts/fetchPosts/fulfilled" happens twice. How to fix it?
Quick way: Remove strict mode from the index.js. Your issue only happens because the new React 18 strict mode mounts components twice. This only happens in development mode with strict mode enabled.
Can this be implemented ina Next.js project normally or do I need to use the Next js wrapper?
I am planning to cover Next.js soon. Next.js is server-side.
@@DaveGrayTeachesCode Awesome! Yeah I know, I'm currently building an application in react next.js and redux tool kit, that's why I asked. lol I've never used next.js and redux tool kit so I'm still pretty green. Just subbed and my notifications are on! Cheers
Hello Dave, i hope this meets you well, I'm having a little challenge with this chapter, when i fetch my data from the typicode API, each post appears twice, and the top post is always inactive, because, when i use a reaction button on the one on top of the similar post, the reacton count does not respond on the first post, but the reaction counts are updated for the second one and not the first one, when i add a new post, it always goes 2nd, because like i said the first post of the similar post that loads with the app when it starts, looks inactive and doesnt even repond to any clicks
Getting duplicate posts is likely due to the concat() in the store.js - This tutorial used React 17 but now, with React 18 in dev mode, each component is mounted twice. Instead of concat, create a new array with brackets and spread in the values [...values]
@@DaveGrayTeachesCode Oh, Bless You Dave. Thanks.. When i land my first job, i will buy you Pizza.
informative and clear
Glad to hear that! 💯
Thank you very much Dave for this tutorial. I have some query though. In the case, fetchPosts.fulfilled, during execution, with this line of code: state.posts = state.posts.concat(loadedPosts) the data is displayed twice hence this warning occured: "react-dom.development.js:86 Warning: Encountered two children with the same key, `1`. Keys should be unique so that...", however, if I changed state.posts = state.posts.concat(loadedPosts) into state.posts = action.payload it displayed okay but I wonder the Time ago and and Reaction also works.
Due to this tutorial was with React 17 and not React 18's double mount behavior in strict mode. Instead of concat, create a new array with the spread operator. See other comments on this.
nice video. thanks
Could you make an Lit Webcomponents + Redux-Thunk. I use it, and could help if you need it.
Hi Dave, thanks for great video, in React 18 , API is calling twice so we are getting one error ' Encountered two children with the same key, ' it's not happening in React 17
It is happening in React 18 with Strict Mode enabled. The new strict mode mounts, unmounts, and then mounts components again. This will be from the useEffect in PostsList.js in this lesson. Discussing this change and others from React 18 here: ua-cam.com/video/N41B_SVdzwg/v-deo.html ...A solution is to keep moving on in this series until you eventually switch over to RTK Query that removes this type of logic from useEffect.
Thanks, Dave Gray for your support
Nice content and teaching. Please help us how to connect it to firebase firestore and get data from firestore using redux thunk. Thanks for the tutorial it amazing
You're welcome! 🙏 And thank you for the request!
Glad I found your channel
Amazing video
Thanks!
Hi Dave, thank you for a nice explanation! I tried to add this logic to my project, which worked well, the only thing is, I think you have a mistake when fetching all data. Im not sure why you use concat method there? I think you want to add new data to an empty array, but this can go wrong as it did it my case, I had duplicated data in the array. Im not sure why, but by default fetchCountries.fulfilled case runs twice and there you get the data duplicated.. Either just assign loadedData to the state without concat or you need to put an additional if statement to check for the status so it doesnt run twice.. Cheers
Hi Darya - there was no problem with the code in React 17 when this tutorial was made. You now have an issue with React 18 Strict Mode as it mounts each component twice. Your fix should work as you noted. You don't want to concat twice. I cover the React 18 strict mode change here: ua-cam.com/video/81faZzp18NM/v-deo.html
@@DaveGrayTeachesCode great, thank you for your advise, I will check this out-)
I have a question, I saw you wrote dispatch inside the useEffect() array at line 17 inside react_redux_toolkit/03_lesson/src/features/posts/PostsList.js
`
useEffect(() => {
if (postStatus === 'idle') {
dispatch(fetchPosts())
}
}, [postStatus, dispatch])
`
what does that mean? isn't dispatch a function? how React is going to know that the dispatch function was changed? it doesn't change, it fires. What If I removed that dispatch from here? what are the downsides?
And thank you 😁
No real downsides I can see other than a possible warning in the console. 💯
@@DaveGrayTeachesCode 👍
thank you for this great tutorial but if you run this in react 18 will get an 100 warning of two children with same key and also blogs are dublicated in page but in react 17 there is no error
React 18 has made some changes. One is rendering twice in strict mode. Not sure this would be the cause but thought of that first.
Had the problem as well, I solved it by instead of .concat the state.posts with the loadedPosts just do state.posts = loadedPosts
@@moretimeproductions thanks for your comment i also solve it with hook useRef
@@kamelkamatchu8830 How did you approach that?
@@moretimeproductions youtube always delete my comment with link .. and as Mr Dave comment react 18 render two times in strict mode and react team already propose solutions for this
I have a question, but this may be due to react 18 rather than a redux issue. I wanted to have the posts load when the component was loaded, so I moved the dispatch statement to the component itself and put the dispatch statement inside of a useEffect. However, I noticed that when I did this that now the redux action fires twice. Upon some more reading, this is because react now unmounts and remounts the component to help devs look out for remountable components when in dev mode. If I remove the React.strictMode tags, the redux action no longer fires twice. Is there a way to prevent this behavior? Or is this why in your videos you load the state upon loading the application?
Ok I found an answer to this and it would be, upon the cleanup of a component, if the promise returned from the dispatch() function is not yet fulfilled, call promise.abort() to abort the calling of the thunk, however, I feel that there has to be a better way
I will love to watch this video
Thank you, Antonio! 🙏
13:50 why dispatch is a dependency in useEffect dependency array?
As recently as React 17, you would receive a warning if it wasn't. It is a function and likely does not change. With React 18 you should not receive a warning if left out.
@@DaveGrayTeachesCode ok, thanks!!
Thanks a lot
You're welcome, Raz! 🙏
Awesome👍👍👍😊
Thank you 🙏
As I refresh the page when I am in SinglePost (say /posts/5), I get error as post not found (my custom error if post not found by id). Why?
Other things work fine. I can navigate to specific post as I click on visit post but refreshing this page is causing error.
I tried logging out the posts in SinglePost component and it is empty
This is a single page app (SPA) as all React apps are. When you refresh the page, you lose your client-side state. It's like restarting an app.
For some reason my extra reducer is not catching the error. I tested error handling and the case for rejected never gets trigger. Looking at the thunk function, I can see that it does catch the error. I'm not sure what could be wrong here. Could you advise what could be the potential issuel
I can only guess from here. Compare your code to mine for differences. The source code is available at the course resources link in the description.
@@DaveGrayTeachesCode sure, but I also comprare it to the documentation and nothing seems different. I might have added a Middleware km the rootreducer, but how would this change the hook? :O
I am trouble in getting the source code for code debugging. please can u post github link on description? thank u
There is a link to the course resources which includes source code in the description. On the course resources page, each chapter of this series is linked to with source code available.
So much coding required when redux is used. But this is a good demo video
Glad it was helpful! 💯
What is your color theme please?
GitHub theme 🚀
Awesome Tutorial +++++++++++++++++++++++