This content is a comprehensive tutorial series on learning React with Redux, focusing on modern implementation using Redux Toolkit. It guides beginners through setting up Redux Toolkit, managing global state, handling asynchronous operations with Redux Thunk and RTK Query, implementing CRUD operations, and optimizing React components.
Mind Map
Click to expand
Click to explore the full interactive mind map • Zoom, pan, and navigate
[Music]
hello and welcome to four hours of react
and redux tutorials and instruction this
video is made up of seven tutorials for
learning redux with react that build
upon each other much like the chapters
of a book
before beginning i recommend that you
already know the basics of react this
video is for redux beginners but not
absolute beginners in react throughout
the lessons in this video i will mention
links being available in the description
below i've compiled all of these links
into one github resource that you will
find in the description hi i'm dave gray
and i'm the creator of these redux with
react tutorials you can subscribe to my
youtube channel for more tutorials like
this one you can also follow me on
twitter and if you're feeling generous
you can even buy me a cup of coffee
let's get started learning redux with
chapter one overall redux is a global
state manager that allows you to manage
your app state in a single place which
can be very useful
the creators of redux now recommend
implementing redux through the use of
redux tool kit redux toolkit addresses
several common complaints about redux
including complex store configuration
too many added packages and too much
code to implement overall
long story short redux toolkit is an
easier modern way to implement the power
of redux as a global state manager today
we're going to create a simple example
project to learn how to set up redux
toolkit and get some initial exposure to
how it all works so you can see here in
visual studio code i have a basic
project set up with very few
dependencies so i've removed the things
already that we will not be using i used
create react app of course to create the project
project
and then in the index.js i've removed
some of the boilerplate code that we
don't usually use the same with the
app.js and in the index.css i've put in
some of my own css but of course you
could get this from the source code in
the description or you could just create
your own what we're going to focus on
today though is the logic of redux
toolkit so back at the package json i'm
going to open up a terminal window and
we're going to go ahead and install
redux toolkit okay we're going to use
npm install and then we'll put the at
symbol and redux js slash kit
kit
and then put react dash redux and press
enter and this will install and as soon
as it completes will be up and running
and it's already ready to go okay i'm
going to close out of the terminal
window and in the source folder or the
source directory of our file tree let's
create another directory and name this
app in all lower case now inside the app
directory we're going to create a store
and we'll just name it store.js
okay redux store and redux are kind of
used interchangeably both stand for a
container for javascript apps and it
stores the whole state of the app in an
immutable object tree and really the
intended pattern for redux is just to
have a single store for your application
multiple stores are possible but that is
not what is recommended by the creators
of redux to start our store we're going
to import and then we want to import
configure store from redux js slash
toolkit and after we have that let's go
ahead and just say export
const set the store equal to
that configure store
and now inside the configure store we
have an object and it holds a reducer
now this reducer is going to be empty
for now but we're going to come back and
put in reducers that we create
so we'll just save this file after
creating our store we need to go back to
the index js and import that so let's import
import
now we'll have store
and let's go ahead and say that is from
our dot slash app and then slash store
and besides that import we also need to import
import
a provider which will provide this
global state to our app so that comes from
from
react dash redux
and now that we have the provider if
you're familiar with the context api and
the use context hook
this looks very familiar because we're
just going to wrap the app in the provider
provider
and now we say store equal to store so
we're passing that in
and then we're going to have a closing
tag for the provider of course and that
needs to come after our app so we're
wrapping the app with the provider and
now our store our global state will be
available to the app with that complete
we need to create a features directory
inside of our source directory so i'll
click for a new directory and now i want
to type
features and now inside of this
directory we're going to create another
directory for our counter because we're
creating a counter example today so that
is one of the features and now this
counter will have a slice
and the name slice comes from splitting
up redux state objects into multiple
slices of state so a slice is really a
collection of reducer logic and actions
for a single feature in the app for
example a blog might have a slice for
posts and another slice for comments you
would handle the logic of each
differently so they each get their own
slice so now for the counter we're going
to create a slice so we're in the
counter folder and i'll create a new
file here and i'll name this counter
slice with camelcase so a capital s dot
js we'll start the counter slice with an
import and here we need to import
create slice and it comes from redux js
toolkit and now we're going to create an
initial state
so that's exactly what we'll name this const
const
and here we'll set this equal to count
count
and we'll just start it with a value of zero
zero
now after that we need to go ahead and
start to create our counter slice so
i'll just type export const
now counter slice
slice
we'll set this equal to our create slice
that we've imported and now an object
inside of it it starts with a name so
let's just name this counter
after that the second argument that will
be passed in or the parameter as we
define this is the initial state
state
and then after that we have reducers
and now this is where we would name all
of our different actions this starts to
look similar to the use reducer hook
that is built in
to react already so if you're familiar
with that that will help but we're going
to create a couple of actions for our
counter one is increment
and now we'll have an anonymous function
here that receives the state
and inside this we'll take the
state.count that we defined above in our
initial state and we'll just add one to
the total and now i'm going to highlight this
this
press shift alt the down arrow to copy
it down but remember we need a comma
because this is an object so we have our
increment and now let's change this
increment to
decrement which means we need to change
the plus symbol to a minus and so this
subtracts one from the total two so
we've created two actions inside of our reducer
reducer
now we need to export both our actions
and our reducer so here i'll say export
const and we'll destructure those
actions so we have increment
and decrement
and then those are destructured from our
counter slice
dot actions and it looks like i need to press
press
alt z to wrap the code i'm going to
scroll this up so you can see it a
little better as well actually i can
just press ctrl b right now and you can
see it all in one line that hides the
file tree
okay and at the bottom we need to say export
export
default and here we'll take our counter
slice again that we've created and this
is the full reducer that we export here
so let's save now both of these must be
exported if we want to use these actions
we need to export them and we can see
they're available from the counter slice
dot actions we also need to export the
full reducer because the store will need
that okay let's show the file tree again
and now let's go back to the store
because we need to import our reducer so
at the top
we'll say import and this will be
counter reducer
and that will be from now we'll have two dots
dots features
features
and then counter and finally
counter slice and i'll press alt z to
wrap this code so we can see it all at
once now that we have the counter
reducer we need to put it here in the
reducer object where we save some space
for it so we'll say counter and then counter
counter
reducer and save now we could easily
have other slices that we're importing
as well to the same store so we need to
remember that and you might want to save
a comma after each one and it doesn't
hurt to have the comma even if you only
have one in here now that we've added
the counter reducer to the store it is
available to the entire app through the
provider that we put here in the index
js and you can see the provider provides
the store so with that available let's
now create our counter component inside
of the counter directory and we will
have that logic available to us so let's
go ahead and create counter with a
capital ce.js
now i have react es7 snippets installed
so i can type rafce and press enter and
i get a functional expression component
created quickly so if you don't have
that you might want to look into that
extension or just type out this basic
stuff right here for our functional component
component
now at the top of the file i want to
import i'm going to import a couple of
hooks from redux one is called use
selector and the other one is use dispatch
dispatch
and now that i have those imported let's
go ahead and import our actions that we
created so we have an increment
and a decrement that we both created
inside of that reducer the counter slice
actually the counter reducer that's in
the counter slice
so this will come from
the counter slice which we're already in
the folder where it is so it's easy to
navigate to with the imports complete
let's go ahead and add our state to the
component so here we'll have our count
and we'll set that equal to
use selector
now inside the selector we'll reference
the state
now i'll have an arrow and i'll say state
state
dot counter dot count once again i can
see i'm exceeding the width so i'm going
to press
ctrl b to hide that file tree for now so
we'll just stay in the component and you
can see all of the code okay after count
is defined i also want to define the dispatch
dispatch
and now with the dispatch we'll just set
that equal to use dispatch
dispatch
we're now ready to add some jsx to the
code here so i'm going to eliminate this
div that we have and inside the jsx i'm
going to create a section element
and then inside of the section element a
paragraph and the paragraph is just
going to display our count state
and after the paragraph i'm going to add
a div
and inside the div i'm going to have a button
button
and this button is just going to have a
plus symbol and then i could copy that down
down
and then create one with a minus symbol
now both of these need an on click as
well so we'll set the on click equal to
now we'll have an anonymous function and
inside the anonymous function
we can call
the dispatch and inside the dispatch we
can pass any of those actions we created
so here we'll have the increment
increment
and now we call that inside the dispatch
as well and actually i'll copy this down
once again i should have waited to copy
down before
get rid of that extra button and now
we'll just change this
to our decrement
and we'll change that plus symbol to a minus
minus
and that's our basic jsx here for the counter
counter
now we need to go back to the file tree
into our app.js and we'll import the
counter at the top
so we'll say import counter
counter
and that's not what i wanted i just
needed to import the counter component
so import
counter from and here it will be from features
features
and then counter
and finally there's our counter file
okay inside the jsx
we'll just put in
the counter component and save now we're
ready to open up a terminal window with
control and backtick type npm start
and we'll see what happens with our app
i'm going to drag over the visual studio
code window so we can see both actually
here we go so we've got the code on the
left and the app on the right
hide the file tree so we see more of the code
code
okay plus
that's working just fine decrement here
so increment
decrement everything's good with the
basic app function here and of course
this is a very simple example so it just
shows you kind of how redux toolkit is
set up and the structure overall for an
application let's go ahead and add a
couple of more actions so you can
experiment a little bit with the pattern
and see how more actions would be added
i'm going to drag the code back over to
full screen
and now that we have that i'll close the
terminal to add the new actions we need
to go to our counter slice file and
we'll just add more actions right here
in this reducers object so the first one
i want to add is a reset which is simply
going to reset everything for us so
we'll have our state
and we'll set this to an anonymous
function and here the state dot count
will just be set to zero so it resets
the value for us
now the next one i want to add will be
just a little more complex but not too
bad we'll call this increment by
by amount
amount
now it's going to receive not only the state
state
but an action
and now inside we'll go ahead and say state.count
state.count
this is going to be actually plus equal
and now we'll set the action dot payload
once again this kind of goes back to
referencing the use reducer hook because
it also has payloads so here this will
be an amount that we pass in and it will
be in the payload of this function now
after we add new actions we have to
remember to go ahead and export those as
well so here we'll export reset along
with it and then increment by amount and
save now we've already exported our
reducer to the store so we don't need to
do that again we've just added these new
actions so let's just go back to the
component and we can put these actions
to work for us so we have increment and
decrement and i'm going to put these on
separate lines now so increment decrement
decrement
and after that we're going to have reset
reset
and after that we'll have
increment if i could spell increment
there we go increment by amount
and then we'll put that on another line
and save that much to get the formatting
so now we have our actions imported and
i'm going to need to do one other import here
here
and this will be import
use state
and there it is from react because we're
going to use that for the amount that we
choose to increment by
so now besides these hooks that we have
here let's go ahead and set up our state
for that increment amount
and let's just call it that increment
increment amount
amount
now i'll set that equal to use state and
we'll just start out with a value of
zero i'm going to define one more
variable here and it's just because
we're going to use a text input so
we need to verify that we get a number
value so we'll say increment amount
which is the state
and if it is not a number we're checking
it right there we'll just use the short
circuit to set it equal to zero so we
don't get a not a number value returned
and this will ensure we have a number
either added or it will at least be zero
if a number is not in the input
and now a quick function definition and
i'll call this reset all
because i would not only want to reset
the state i want to reset our use state
value of the increment amount as well so
we'll say set
increment amount and we'll set that to
zero and then we'll also use our
dispatch that will set our global state
using the reset action
and that will be set back to zero as
well with that action that we defined
now let's put these to work inside the
jsx so inside of this section that we've
already created
let's go ahead and add an input element
and besides the input it says type text
i guess that would be okay
let's put this on another line and tab
in there we go
so besides the text attribute let's go
ahead and add a value attribute to make
this a controlled input and it will have
the increment amount that we defined in
use state
and then it's going to have an on change
and we set that equal to an anonymous
function that gets
the event and then inside of this we'll
say set
increment amount and we pass in the
e.target.value so just a traditional
controlled input for us after the input
i'm going to scroll up for some more
room i want to add another div
and then inside the div i'm going to
have two buttons again so i'll have a button
button
and let's say on this button
add amount and let's go ahead and add
the on click here for the button as well so
so
on click
equals an anonymous function
and our pattern before stays the same so
then we call dispatch
and now we'll say
increment by amount which is a little
bit longer name for our action but
that's what it is and then we'll just
pass in that add value variable that i
defined above i'm going to press
alt z to wrap the code so you can see it
all so we defined add value to make sure
that it was a number so it's either
0 or the number that is input and that
was defined above but here we're calling
our action with dispatch once again now
i'm going to copy this down and the on
click here for the second button will be
much simpler we'll just pass in
the reset all function that we defined above
above
and here instead of add amount we'll
just put
reset just one t and save okay i'm going
to drag visual studio code over to the
left and we can see our component it now
has the new input and the new buttons as
well so any amount that we add here say
10 and we click add amount
our state is going up by tens and if we
reset yes it sets both to zero see if we
can put in a negative number
negative two and we add yep that works
too so anything we put in here and of
course an abc shouldn't work it should
identify so yeah it's just zero there so
that doesn't change anything so if we go
by twos we can go back up
all good so our app is working and
overall this shows you how to implement
a simple state and some basic actions
and get the whole redux toolkit
structure up and running
to better understand redux app structure
and data flow today we'll be building a
simple react bulletin board app and
manage the global state with redux
toolkit in visual studio code you can
see i've got a project already open and
i've already installed redux toolkit and
essentially you can get this starter
code you could download it from the
source code link in the description for
the resources or you could just delete
the counter feature from the first
tutorial in this series if you've
completed that and you'll have this
beginner code so we've already got redux
toolkit installed and you can see react
here in the dependencies after that if
we go to the index you'll see we've
already imported the store and the
provider we're providing the store to
the app and of course the store is
created and we don't have a reducer in
here right now because i've removed that
counter feature that we had in the first
tutorial of this series so this is
basically where you want to start
anytime you would use redux toolkit with
an app as far as creating a store
importing that store and the provider
and then providing the store for the
global state to the app so we've got
that completed already i've got some css
that you can get from the resources as
well if you download the code or you can
just supply your own and then in the app
we have just a basic function component
here that is empty i've switched the div
you typically get to a main element and
that's about it so let's get started our
first step today will be to add a new
feature in our features directory and if
you don't have a features directory go
ahead and create one now inside of the
source directory so here we're going to
add a posts feature so we'll add a post
directory and then inside the post
directory let's create a posts slice and
slice is where we divide up our state so
this will have everything to do with the
posts we create and we want to start
with import
create slice and that should come from
redux toolkit and there it is now i'm
going to just paste in some code and we
can see what we would have in this slice
so we start with an initial state and i
have just hard coded in a couple of
posts i'm going to press ctrl b to hide
the file tree right now so you can see
all of that
and so we just have two posts with id
title and content and this is an array
with two objects really and then we've
got our post slice that we create and it
accepts a name so we name that post then
we pass in the initial state that i've
just hard coded above then we have
reducers which i haven't supplied any of
those yet and then we export the post
slice reducer okay i'll save this file
we'll show the file tree again because
any time we create a reducer like this
we need to add it to the store so let's
go back to the store.js now and here we
need to import the reducer so we're
going to
import posts
reducer and this will come from and then
we go up a folder and then we go into
the features folder and then we go into
the post folder and finally we find our
post slice right there okay after we've
imported that we need to put it in the
reducer as well so here we'll say
posts and then we pass in the posts
reducer and we could put a comma now or
we could do it later when we add another
reducer right now we'll just leave it
like this and save now back in our posts
feature we need to go ahead and create a
post list component so let's call this posts
posts
list dot js
and we'll start this out by importing
the use selector so we'll say import use
selector and that comes from react redux
after that we can create a functional
component and i'll type r a f c e
because i have es7 snippets installed
press tab
and i have a functional component
already created for me so that helps out
quite a bit but i'm going to change
what's inside of it so i'll just select
this return and i'm going to paste in
the rest of the code and we'll quickly review
review
so now we're using the selector that we
imported and you can see we've got the
state and we're just getting all the
posts that are in our state after that
we're defining rendered posts so we're
mapping over the posts and we're
creating an article for each post
essentially creating a post here for
each one that's contained in post we
pull in the id the title and the content
notice we're using sub string so we're
just getting the first 100 characters
there for that to preview essentially
the post if it was a long post
and then we're using the rendered post
in the jsx so we've kind of pulled that
logic up here instead of putting it in
the jsx and it makes that jsx very clean
and then of course we're exporting the
post list here at the bottom and we save
the file now before we move on and use
this component we need to talk about
this use selector because right now it
receives the state and then we get
state.post but what if the structure of
our state changed right now this
component needs to know something about
the state it needs to know we go state
dot post it could be state dot post dot
something else in the future we don't know
know
so it would be better if we create a selector
selector
in the slice and then export it and that
way if the shape of the state ever
changed we wouldn't have to go through
and change each component we could just
change it once in the slice so let's do
that we'll go back to the slice and here
just above the export default we'll go
ahead and say export
const and then let's call this select
all posts
and we'll set this equal to an anonymous
function that receives the state
and essentially does what we did have in
the component so here's our state post
so this selects all the posts but we're
exporting this now
so let's save this and then we can
import it into our post list
so here we will say import
import select
select
all posts and that comes from our post slice
slice
and then we can just use it right here
instead of what we did have in the use
selector so we'll say select
all posts and this will work in the same
way but now if the shape of the state
ever changes essentially we'll just need
to change it in the slice and not in
every component now let's go to our
app.js and import the post list
component so we'll say import
posts list and there i see it in the
list below and that comes from our
features posts and then the post list
component and now we can use it inside
the main element here in the jsx so
here's our post list
and save and now let's go ahead and open
a terminal window with control back tick
and type npm start to just see our
progress so far and i'm going to pull
visual studio code over here to the left
side of the screen and we should see our
react app start up over here in a new tab
tab
on the right side of the screen
and there we are so we've got posts and
we've got our two posts it says learning
redux toolkit and the body says i've
heard good things then we've got slices
and yes the more i say slices the more i
want pizza so that is what we had in our
state if we pull this back over
and we look at this i'll close the
terminal here
but let's go back to the post slice and
here is our state i'll hide the file
tree so we can see it all and there were
our two posts so yes they appeared as we
expected now we want to be able to add
new posts with a form but before we do
that we really need to create a reducer
function that will handle the data we
submit so we're going to create a post
added function that goes here inside of
the reducers in the slice i'm going to
paste this in
and we'll take a look at it so we've got
post added it receives the state and an
action and then we get the payload which
would be the form data that we send or
we actually dispatch when we dispatch
our post added so we dispatch the action
and then it of course has the payload
that is the form data and then notice
we're pushing this to state now we'll
talk about this state.push in just a
second because if you are familiar
enough with react you know we don't
usually mutate state and that's what dot
push would do to an array so we'll talk
about that in just a second but right
now after we add post added we also need
to export that so just under our
selector let's say export
const and then we'll have post added
and then that's going to equal posts
posts slice
slice
if we can type that right slice dot
actions and we save so when we write
this post added function then create
slice automatically generates an action
creator function with the same name now
when we export our actions we're
actually exporting this action creator
function that is automatically created
so that's why you don't see post slice
dot actions above it's just
automatically created so i know that
could look a little confusing at first
but that is how that works now let's
talk about the state dot push and i'm
used to writing state like i would
spread in the state and then have the
action payload as a new item instead of
state.push but react toolkit uses immer
js under the hood and that allows you to
write your javascript like this where
you would normally be mutating the state
but it is not mutating the state mr.js
creates new state underneath now realize
this only works inside of the create
slice anywhere else in your application
you still need to use the proper way of
not mutating the state that you've
probably learned as you learned react if
not before however inside of the create
slice you can use state dot push and you
can directly set the state in other ways
as well and emerge a s will handle that
so it makes it easier to handle inside
of here and if you're curious i'm going
to provide a link below in the
description to the page for
emmer.js now that we have our reducer
function to handle the form data and
we've exported an action creator let's
go back to our file tree and we need to
create a new component and that would be
the form components let's call this add post
post
form dot js now at the top i'm going to
import use state
and there i see it in the list
after we've done that i'm going to use
raf c e once again and press tab and now
we've got the outline of our add post
form component
and then once again inside i'm just
going to select what we have here and
paste the basic form component and we
can go over it it looks like is there an
error somewhere possibly i'll find that
as we go with a short discussion here
we've got use state so just because
we're using redux doesn't mean we won't
use state in some components because
this is a temporary state it's just a
controlled form input for title and
content and so we don't really need to
send those to the global state they're
just for this component so we only want
to send things to the global state that
other components would possibly use
throughout the application and
eventually we could expand this
application where other components would
be using what we're sending to the
global state although this is a simple
example nevertheless title and content
are just going to be using state here
because it's only for this component now
as we scroll down we can see we've got
an on title changed and an on content
changed and they're just using the set
title and set content and getting the
event target value and that's a typical
controlled form so that's essentially
what we have here in our form and let's
see if we can find where that error is
it looks like we're missing a
parenthesis down here yep and now if we
save there's no more error and we're
exporting here at the bottom so again a
basic form you can download the source
code or create it on your own but you've
got a form label input
controlled value and of course the on
change event for each one of these we
have not added the save logic yet so we
don't currently have an on click in the
button to save the post but that's
coming right up let's go ahead and add
the logic that we'll need to save any
new post so at the top once again we
need to import and this will be use
dispatch there i see it in our list
and that comes from react redux and now
we also want to
import a
nano id there it is and that comes from
redux js toolkit nano id will help us
generate a random id so you don't need
to import something else like a package
like uuid or something like that redux
js toolkit already has nano id okay one
more import let's go ahead and import
import post
post added
added
from our post slice and now we can use
that inside of the ad post form okay
let's scroll just a little bit and
underneath our on content changed we're
going to add an on save post clicked and
i'll go ahead and copy and paste this in
and we will break it down let me save
just so it formats better okay our on
save post clicked function and this is
what we will trigger with the button in
our form to save we're checking to see
if we have title and if we have content
value then we're going to dispatch our
post added action and then that will get
the id that we create with the nano id
that we imported above from redux
toolkit and it will also pass the title
and the content notice these are in an
object and then we're just setting the
local state for the title and the content
content
back to empty and that should pretty
much be it so now all we need to do is
go to our button and add the on click
here at the bottom so besides the type
form which we could put on a separate
line and we'll break that down to a
separate line as well and come over
let's put our on click right here so we
have on click
click
we'll set this equal to on save post
click and save okay i'll drag visual
studio code back over to the left and we
can look at this what we haven't done
yet i guess is provide the form to the
app.js so once again i'll drag this back
real quick we've exported the form so
now let's go ahead and import it to the
app.js and so that will be here and
we'll say import
import
and this would be the add post
post
form there we go and not an abbreviation
but there it is from our features post
ad post form
and then once we have that we just need
to add it to the jsx so let's add it
above the post list so we'll say add
post form
close it out there and save now let's go
back and see if it's showing up and if
we can add something and it looks like i
missed importing the dispatch into the
form so once again i'm dragging back i'm
going to go to the form look at the top
here i've got use dispatch
but we didn't set the dispatch once we
got down into the form and of course we
need to do that as well so we've got
dispatch right here let's just set it
right here at the top we'll say const dispatch
dispatch
i can spell dispatch there we go set it
equal to use dispatch
dispatch
and there we should be good to go now so
let's go back
this time we're ready to go so we can
add a new post and here i'm just going
to say
hey there test12
test12 enter
enter
and we've got our new post at the bottom
of our post list right now so the two
existing ones we had and then our new
post is down here so everything's
working as expected so far
so right now the form is working but it
could be better and let's talk about
that that's because right now it needs
to know the details about the state once
again in order to send it properly it
has to send a properly formatted object
and it would be better if we could
abstract some of that we don't want to
duplicate this type of logic in every
component that posts to our global state
so instead we can handle this back in
the slice with a prepare callback and a
prepare callback can generate unique ids
format the data return the object with
the payload and that's basically kind of
what we're doing here so this will
really simplify our component and it
will handle everything once again back
in the slice so let's go to the slice so
our first step here will be to add a
colon after post added
and start another curly bracket there
and so of course we'll have another
curly bracket underneath as well
and we could save that much to get the
proper formatting i think well maybe not
what am i missing so we'll fix this in
just a second i guess we need to put
reducer right here and then we have a
state action of course we've got our
colon curly bracket reducer state action
we've still got the state.push with the
action.payload there oh and then we need
a comma afterwards so let's go ahead and
do that and then tab this in
and then as we tab over our post added
looks better already and now let's put
our prepare callback in here right after
the reducer so it's still under post
added and now you can see we have
prepare here and here we're passing in
the title and the content that we would
get from the component and then it
returns the action payload as it needs
to be formatted so we have a return here
and then we have our payload and this is
where we define the id with nano id so
we're going to need to import that here
in our slice
title and content and it looks like
underneath here maybe we need one more
curly bracket yep to stop that error but
that of course provides a reducer and a
prepare callback for our post added
reducer function so let's save this now
and then we'll go back to the top and
import that nano id before we forget
there we go and now we've got both of
those imported as well and now let's go
back to the add post form where we can
simplify what we're doing right here so
instead of everything we were passing to
the post added before we'll just say title
title
and content and the rest will really be handled
handled
inside of our prepare callback function
and the benefit here is that our
component once again doesn't even have
to know the structure of the state at
all all of that is now handled inside of
the slice and we can just send the raw
data that we need to now grab visual
studio code drag it to the left and we
can try another post again so i'll say
hey hey
and then my my
save the post and we look here at the
bottom and we've got hey hey my my for
the new post now the one we created
before of course isn't there because
we've modified the code and saved it and
then of course that is removed but
overall everything is working as we
expect now this is a good time to also
bring up that there is such a thing as
redux dev tools so let me grab that link
for you and then i'll bring it over here
and put it in a new tab
and if we go to redux dev tools this is
the github page and i'll link to this in
the description
we can see that redux dev tools is a
browser extension it's available for
chrome edge and firefox also as a
standalone app or even a react component
and it's a pretty good way to check your
state and make sure things are working
as you expect them to inside of your app
so i'll open up dev tools and then after
you've installed that i'm in chrome i'll
go down here to redux
select that and we can see here's our
raw state it's a tree right now that
we're looking at if i drag this up a
little i'm not so sure i can do that
i've got a shorter screen sometimes so
there we go i've got the posts and each
one of these are showing in a tree you
can also see a chart and of course it'd
be nice to have a little more room to
see the chart but i'm shrinking it with
the scroll wheel and there we can see
it's pretty simple right now because we
have a simple state
and then we can see it raw so here we
can actually see each post inside of our
raw and then you can also see the
difference so you can see the last
action that was called into action
essentially and i'm trying to find
something to drag here but i don't see
anything to make this bigger for you on
on my screen currently if i were to
shrink my font and everything as far as
my zoom it would probably be easier to
see but anyway all of this is there you
can install redux dev tools as a chrome
extension or whatever browser you're
using it looks like it's available for
edge and firefox as well a react
component or a standalone application
and this might help you as you work with
redux so i definitely wanted to mention
it i'm going to close devtools now
and drag the browser back over here to
the right i'll drag visual studio code
back to full screen display and now we
want to add users to the application so
we can credit the post to their authors
but we want to keep this as a separate
feature so we want to separate all the
logic and data from the post slice and
we'll create a new feature called users
so inside of our features directory
let's create another directory here
called users and i'm on the wrong keys
there we go
users and then inside of users will
create a users slice so again users
slice dot js now inside of user slice
we're going to import
create slice there it is in our list and
we get that from redux toolkit and then
i'm going to paste in the rest and we'll
quickly go over it as well you can see
once again i've just got a hard-coded
initial state here with three users and
then the user slice has a name it gives
the initial state and right now the
reducers are empty
notice i already created a select all
users selector here that we can export
and then we're exporting the default
user slice dot reducer so we need to put
that in the store which will be our next
stop so let's go to the store.js and now
at the top here we'll say import users
users
reducer and that will come from again
two dots
features now users and they're inside
we'll find our user slice and here we'll
just put it after the post reducer so
we'll put a comma and then users
and we'll have our users reducer
reducer
so now when posts are made we want to go
ahead and add the user id to the post so
then we can look up the username and of
course give them credit with the post so
let's go back to the post slice
and there we need to go ahead and change
this prepare to also accept a user id so
we'll put user id right here and then
we're of course going to put that
inside of the payload as well so here
we'll just have
user id and now to send this user id
data to the prepare function we need to
go back where it is coming from and that
is the add post form so at the top we're
going to do a couple of things we've got
use dispatch let's go ahead and bring in
the use selector
and now of course you can see we changed
our code earlier when we simplified it
with that prepare function in the slice
so we don't need the nano id here
anymore we can remove that import but
then underneath our import of post added
let's go ahead and import and here it
will be the select
select
all users and that comes from our user
slice okay now that we have that we also
need to have some more temporary state
so we could just press shift alt and the
down arrow to copy down the content
state and we'll select content here and
change this to
users and set users or do i want user id
i actually i want user id there so let
me select both users and say user
id that looks better so that's a
temporary state that we will track here
in the component
and we will pass along with whatever the
post is then to the global state now we
need to go ahead and get our users so
here we'll say const users and let's set
this equal to the use selector that we imported
imported
and then inside of there we'll use the select
select
and there we'll save oh i left off the s
there it is and now save now just like
we added to the state where we have user
id we're going to need a content changed
here as well so we'll take this down and
we can change this instead of on content
changed let's call this on
author changed and then inside of that
on author changed instead of set author
here which would also make sense we're
going to set user id and i noticed i
left a t there in the author so there we
go now on author changed now inside of
our dispatch with the post added we're
going to have the title content and the
user id to send as well okay underneath
the on save post click i'm going to go
ahead and create the options menu right
here called user options so let's
quickly look at this we're mapping over
the users we brought in and then we're
using an option element to have a key
and a value and then we display the user
name but of course the value that we are sending
sending
is that user id and that's what we will
grab with our on author change that sets
the user id here and then we send that
user id state that we set above
right here to our post added function so
now let's add those options to our form
and i'm going to put them between the
title and the content i believe so we'll
just put it right here
and paste that in we'll get it
reformatted but you can see we have a
label for the select element
and then of course the options here go
inside but we're starting out with one
blank option as well now there's one
more thing we can do for this form so
i'm going to scroll back up and just
above user options here i'll paste this
in we're defining can save and we're
essentially checking to see if the title
the content and the user id are all true
right here and if that is true then if
can save is true
we can enable or disable the form button
so let's go ahead and do that we'll
scroll down here and let's look at the
different attributes for the button and
we'll set this last one to
disabled which disabled would be true if
you could not click the button so what
we want to do is say the opposite of can
save so if can save is true then
disabled is false and save our file and
now we should be able to see how this
works so i'll quickly drag visual studio
code to the left and you can see our
button is disabled but now if we put in
the post title and i say
my rug and then here
i'll choose dude lebowski
and then i can say
they took my rug and you can see as soon
as we have content in all three of these
the button is enabled but if we remove
the content
the button is not working so that's the
goal we wanted there
now we're sending the user id from our
form as we dispatch our post
added right here our post added function
so we're sending all this back to the
prepare callback that then gets added as
a payload but what we haven't done yet
is set anything to actually display the
author so we need to do that next and
we'll do that by creating a new
component inside of the posts feature
so here we go and let's call this post
post
js we'll start at the top by importing
the use selector and after we get use
selector we also want to import select
select
all users
and now after we have both of those i'm
going to use rafce once again press tab
and we get a post author component this
is a simple component once again i'll
remove what is inside of it and just
paste in some of the logic here so we've
got our users and we're using the use
selector with our select all users
selector that we created in the slice
and now
we're defining author and here we call
the find array method on
users and we're just finding the author
so once we get the author if he exists
he or she i should say
then we display the name but if the
author doesn't exist or just isn't there
at all i guess if you can't find the
number or one hasn't been provided then
we get unknown author and that's a very
simple component so let's go ahead and
save now let's go to the post list and
import this component so here we'll say import
import
post author and i see it popping up in
our list and then once we've got the
post author we'll put it below the title
and the content
and i've got just a little bit of
formatting here so i'll save i can
remove that empty line if we want but
what i've got is a paragraph and i
applied a class called post credit and
now we have our post author component
and you can see
the user id is passed from the post dot
user and this needs to be user id right
here there we go and save now we'll look
at the results in just a second but now
if we go back and look at our post slice
remember our initial state we didn't
provide a user id here we have a post id
a title and content so let's see what
happens with that as well as any new
post we create that should have a user
id so i'm going to drag this to the left
and i've got a user id problem here in
the post author we just created so i
think i know what it is and yes we
forgot to pass it in up here so this is
really what we need to destructure and
have the user id to receive the prop
that is being passed in so we put that
pass it into the post author and all
should be good let's go back and look at
the post list once again where that is
passed in and so here we go user id is
being passed in so we needed to receive
it and that's what was missing okay
dragging this back to the left we're all
good to go here we've got dude lebowski
he's saying hey what about my rug and
then he says this
this aggression
aggression
will not stand
and save the post let's take a look and
look we've got an unknown author for the
first two because remember our initial
state doesn't even provide that user id
so it just defaults to unknown author
instead but on the last one we can see
the author is now getting credit now it
would be nice if we could also display
the time the post was made in a
user-friendly way here right beside the
author so let's do that next i'll drag
this back and we'll have visual studio
code in the full screen and this will be
part of the post data so we'll once
again go back to the post slice and i'll
hide the file tree again and we can make
some changes here now the first thing
we're going to need to do is import a
dependency so i'll press ctrl in the
backtick i'm going to
exit right now for the application and
then we can type npm i we're going to
install and then it's date dash fns and
we'll install this date fns package that
will help us display the date in a
friendly way for users and with that
completed we can close the terminal and
we'll have to restart the app in just a
minute but right now we'll go to the top
and we'll import sub
sub from
from
date dash fns
okay we've got sub imported and now we
need to add the date to our initial
state so we'll break these out on
separate lines here now
and now for the last part
we'll put in the date and here we'll have
have date
date
and let me break this onto another line
and i'll click up here and i'll just
paste this in real quick but you can see
we're using sub
so we're taking a new date object and
then we're essentially subtracting 10
minutes and then we're also converting
this to a string we could remove the
comma for now if we want to
but this is how we're storing the data
as this iso string so it's converting to
a time stamp string
and let's go ahead and do the same thing
now to our other
post and i'll put a comma here
and come down to the next line and have date
date
and break that down to another line but
here i'll once again paste in the sub
and instead of
10 minutes here we'll make it five
minutes so they have different values
and save this much but before we're
finished we also need to add this to the
prepare now this isn't something that's
going to get passed in like title
content and user id we can just put it
here inside of the content so we'll go
ahead and put it right here
and then i'll just paste it but it's
date and then we're taking whatever the
new date is and converting it to that
timestamp string so essentially right
when the post is made we're creating a
timestamp i'll save this change and then
back in the file tree we need to create
another new component and we'll call
this one time ago
and there i started with the t there we
go time ago.js
and now inside of time ago we'll start
with an import so we're going to import
and this will be
parse iso
and then we're also going to import format
format distance
distance
to now and both of those are going to
come from
date dash fns
after we've done that we can go ahead
and use rafce again if you have es7
snippets installed as the extension and
there we get our time ago component
going to try to avoid the mistake i made
before with the post author and remember
to pass in the timestamp here at the beginning
beginning
after that inside the component i'll
just paste in what we've got fairly
simple again so we start out with a time
ago variable that is empty and now if we
have the timestamp we're going to go
ahead and create the date we're going to
parse that iso that we created parse the timestamp
timestamp
and then we also get the time period
with the format distance to now
and then we set our time ago to time
period ago so it's a user friendly way
to read the date and then we're just
returning that right here so let's save
this and head back to the post list
where we can import this so just like we
imported post author we'll import
time ago
and that is not what i wanted i got the
wrong tab there so i'll try that again import
import
time ago
and there it is now we can put it right
underneath our post author so i'll copy
that line down
change that to
time ago and then this is going to be
time stamp right here
and inside of timestamp whoa got a
little extra inside of timestamp we're
going to put the post dot
date and that's what gets passed in now
we need to restart our app to look at
these changes so once again i'll do npm
start and we'll get that going i'll drag
visual studio code to the left
there we go we've got everything
compiled and let's take a look so we've
got unknown author 10 minutes ago
unknown author five minutes ago let's
try a new post again we'll say hey hey
and then neil young and now we can say
my my
save the post and let's look at the bottom
bottom
less than a minute ago so that is also
working as we expect it to but as we
look at this wouldn't it be nice to see
the new post we made show up here at the
top instead of the bottom so we could
see that new post right away let's make
the changes that will make that happen
so let's drag visual studio code back
i'll close the terminal and now inside
of our post list i'll paste a line of
code and i bet yes i'll need to hide
that file tree again with ctrl b
so let's look at the ordered post that
we're defining we're taking all of the posts
posts
and then let's look at this in reverse
order so we're sorting the posts and
this locale compare will return a
negative one or a positive one or a zero
based on if one is greater than the
other so it converts that date string
and it lets our sort method here or sort
function handle this a b comparison so
then we're sorting all of the posts by
the date string slice is going to return
a shallow copy of the array so we're
essentially creating a new array then
and that's what we're storing in ordered
posts so with that change i need to
select ordered posts and i'll get rid of
this extra line so we're not going to
map over posts anymore here we're going
to map over the ordered posts and now
let's save and once again i'll drag
visual studio code to the left let's
look at everything and hey our neil
young post is still there but it's on
top now so 12 minutes ago seven minutes
ago two minutes ago and you can see that
things are now in that reverse order
that we need so the most recent post is
on top these posts look okay but i think
they would be better if we could
actually add reactions for the posts as
well so let's do that i'll pull visual
studio code back over so we can see it
in the full window and we're at the
posts list right now we need to go back
to the post slice because anytime we add
new data that is the first place to
think about what are we data are we
dealing with it still deals with the
post so this is where we'll go and in
our initial state again for the two
posts that we have in here let's go
ahead and add the reactions here first
so it will be an object so we've got our
reactions object and now we've got five
different options so we'll have five
different reaction buttons and let's do
the same thing for the second post
and we can save that but then we also
need to handle this in that prepare
function as well so any new post that is
created needs to be prepared and have
the same reaction options as well so
there this will go ahead and add the
reactions to any new post and now we
need to add a new reducer that will
actually update the reaction count when
a user clicks any of these buttons so
here we are in the reducers and we've
got post added that has a reducer and a
prepare so let's just follow this down
to the bottom and after post added we'll
put a comma and i'll paste in our new
reducer here which is
reaction added and it receives the state
and the action
and then we're going to
deconstruct the post id and the reaction
from the action payload and there we'll
have the existing post and then we will
find what the post is from the post id
and we'll update the reaction count once again
again
notice this would normally be mutating
the state as we just increased that but because we're in the create slice this
because we're in the create slice this is handled by mr.js
is handled by mr.js and that lets us write code like this
and that lets us write code like this that would normally mutate the state but
that would normally mutate the state but underneath the hood emmer is making sure
underneath the hood emmer is making sure we are not mutating the state remember
we are not mutating the state remember once again you can only do this inside
once again you can only do this inside of the create slice okay now remember
of the create slice okay now remember once we've added this new reducer here
once we've added this new reducer here reaction added
reaction added then redux toolkit automatically creates
then redux toolkit automatically creates that action creator that we need to
that action creator that we need to export to use in the component so then
export to use in the component so then after our post added action creator
after our post added action creator we're also going to export reaction
we're also going to export reaction added and that comes from the post slice
added and that comes from the post slice dot actions now just like we did with
dot actions now just like we did with post author and our time ago component
post author and our time ago component we need to create a reaction buttons
we need to create a reaction buttons component so let's do that
component so let's do that reaction
reaction buttons.js
buttons.js now at the top of reaction buttons we're
now at the top of reaction buttons we're going to import
going to import use dispatch
use dispatch and after use dispatch we're also going
and after use dispatch we're also going to import
to import reaction added and we got that from the
reaction added and we got that from the post slice
post slice and now let's go ahead and paste our
and now let's go ahead and paste our reaction emoji it looks like i missed
reaction emoji it looks like i missed the c and const when i copied that so we
the c and const when i copied that so we have our reaction emoji object now and
have our reaction emoji object now and this provides a object lookup so we have
this provides a object lookup so we have thumbs here thumbs up as the key and
thumbs here thumbs up as the key and then we have the emoji as the value on
then we have the emoji as the value on the right and that follows that same
the right and that follows that same structure now i'm going to come down
structure now i'm going to come down here and use rafce
here and use rafce and that creates our simple component
and that creates our simple component here at first for reaction buttons now
here at first for reaction buttons now once again we're going to receive
once again we're going to receive something and that will be the post
something and that will be the post and then inside of the component i'll
and then inside of the component i'll paste in the body here and we can go
paste in the body here and we can go over it quickly hide the file tree so
over it quickly hide the file tree so you can see it all so we've got the post
you can see it all so we've got the post and here we're creating the dispatch and
and here we're creating the dispatch and then the reaction buttons well it's an
then the reaction buttons well it's an object lookup that we have up here right
object lookup that we have up here right that receives the
that receives the reaction emoji so we say object dot
reaction emoji so we say object dot entries
entries and then we pass in that reaction emoji
and then we pass in that reaction emoji which allows us to map over everything
which allows us to map over everything the key is the name
the key is the name and then the emoji is the value so now
and then the emoji is the value so now once here inside of the jsx that we're
once here inside of the jsx that we're returning we can refer to the name
returning we can refer to the name and then later on we can refer to the
and then later on we can refer to the emoji as well besides that we're
emoji as well besides that we're receiving the post in the component so
receiving the post in the component so here we can dispatch reaction added and
here we can dispatch reaction added and pass in that post id and the reaction
pass in that post id and the reaction that we expect to receive
that we expect to receive back in the post slice where we have the
back in the post slice where we have the reducer and to finish out the component
reducer and to finish out the component we see we're going to return a div that
we see we're going to return a div that contains our reaction buttons jsx that
contains our reaction buttons jsx that we created here and of course we have
we created here and of course we have the default at the bottom now we need to
the default at the bottom now we need to go back to the post list and import this
go back to the post list and import this so here we go we'll import
reaction buttons
buttons from reaction buttons there it is and
from reaction buttons there it is and now inside of our article inside of the
now inside of our article inside of the jsx
jsx we can use this component reaction
we can use this component reaction buttons and now it's going to receive
buttons and now it's going to receive the full post so we just pass in the
the full post so we just pass in the post not posts but post the individual
post not posts but post the individual one and we can save and now let's go
one and we can save and now let's go back and look at our application once
back and look at our application once again i'll drag this to the left and you
again i'll drag this to the left and you can see we've got reaction emojis here
can see we've got reaction emojis here for each post i could even make another
for each post i could even make another new one i can say
new one i can say hey hey
where's my rug that is a reference to the big lebowski
that is a reference to the big lebowski movie by the way if you're not familiar
movie by the way if you're not familiar so here we go we've got our posts we can
so here we go we've got our posts we can say thumbs up
say thumbs up everybody's supporting the dude wanting
everybody's supporting the dude wanting his rug
his rug and everything is keeping count like it
and everything is keeping count like it should looks good
my my from neil young hey hey
hey hey we add that let's look and yes we've
we add that let's look and yes we've still got
still got the count here for dude lebowski's post
the count here for dude lebowski's post and for our unknown post so all the
and for our unknown post so all the reaction emojis are now working as well
reaction emojis are now working as well so i hope overall this has been a very
so i hope overall this has been a very good exercise for learning about the
good exercise for learning about the structure and data flow used in redux
structure and data flow used in redux toolkit
toolkit redux does everything synchronously so
redux does everything synchronously so anything asynchronous has to happen
anything asynchronous has to happen outside the store and this is where
outside the store and this is where redux middleware comes in and the most
redux middleware comes in and the most common async middleware is redux thunk
common async middleware is redux thunk funks are recommended as the standard
funks are recommended as the standard approach for writing async logic with
approach for writing async logic with redux so what does thunk mean
redux so what does thunk mean the word thunk is a programming term
the word thunk is a programming term that means a piece of code that does
that means a piece of code that does some delayed work and that description
some delayed work and that description really fits asynchronous tasks we're
really fits asynchronous tasks we're going to jump right in from where we
going to jump right in from where we left off in part 2 of this redux toolkit
left off in part 2 of this redux toolkit series we created an example bulletin
series we created an example bulletin board project in react with redux
board project in react with redux toolkit you can download this starter
toolkit you can download this starter code from the sources in the description
code from the sources in the description or you can create your own i've got
or you can create your own i've got visual studio code open and our starting
visual studio code open and our starting point today is in the posts slice which
point today is in the posts slice which is inside of the source directory and
is inside of the source directory and then inside of the features directory
then inside of the features directory and finally inside of the posts
and finally inside of the posts directory and then you find the
directory and then you find the postslice.js
postslice.js what we want to do is remove our initial
what we want to do is remove our initial state that we started with we were using
state that we started with we were using a static state and now we're going to
a static state and now we're going to bring in data from an api server so
bring in data from an api server so we'll grab all of this initial state and
we'll grab all of this initial state and redefine it actually i'll just paste it
redefine it actually i'll just paste it in so i also have the initial state
in so i also have the initial state const there so we'll remove all of this
const there so we'll remove all of this just with the backspace and now i'll
just with the backspace and now i'll paste in what we're going to have for
paste in what we're going to have for our state oh and i missed the c on const
our state oh and i missed the c on const so let me add that and now expand this
so let me add that and now expand this once again there we go so now we've got
once again there we go so now we've got our initial state and we've got an
our initial state and we've got an object now and so posts is an empty
object now and so posts is an empty array because we haven't populated or
array because we haven't populated or hydrated that yet if you will and then
hydrated that yet if you will and then the status is set to idle and notice
the status is set to idle and notice i've got a comment here because these
i've got a comment here because these are the different values we're going to
are the different values we're going to use either idle loading succeeded or
use either idle loading succeeded or failed and then we've got a spot to hold
failed and then we've got a spot to hold an error if we do receive one and we
an error if we do receive one and we just set that to null to start out now
just set that to null to start out now we need to consider that our initial
we need to consider that our initial state has changed and since it's an
state has changed and since it's an object it is no longer just going to be
object it is no longer just going to be state dot posts we actually have a posts
state dot posts we actually have a posts property so we need to change what we
property so we need to change what we have here so let's find the different
have here so let's find the different references to state and i'm going to do
references to state and i'm going to do that by pressing control
that by pressing control d
d actually i want to press control f to
actually i want to press control f to find the first one and i'll then search
find the first one and i'll then search for state and then a dot after and you
for state and then a dot after and you can see i found the first one and it
can see i found the first one and it says there are three so now i can just
says there are three so now i can just highlight the first one state dot i'll
highlight the first one state dot i'll press ctrl d to select the next one and
press ctrl d to select the next one and the next one and we're going to change
the next one and we're going to change all of these so i'll press the right
all of these so i'll press the right arrow to go to the end and we need to
arrow to go to the end and we need to add posts after this so then we'll add
add posts after this so then we'll add posts and a dot actually so everything
posts and a dot actually so everything works and i know that makes it look a
works and i know that makes it look a little weird because we have
little weird because we have state.posts.posts
state.posts.posts but that's what it ends up being because
but that's what it ends up being because we now have an object and then we also
we now have an object and then we also have the name here inside of our slice
have the name here inside of our slice that is posts so we have state dot posts
that is posts so we have state dot posts dot post when we refer to that inside of
dot post when we refer to that inside of our selector here with select all post
our selector here with select all post other than that we should also have
other than that we should also have state dot post dot find inside of the
state dot post dot find inside of the reaction added and then we should have
reaction added and then we should have state dot post dot push inside of the
state dot post dot push inside of the post added reducer in an important
post added reducer in an important footnote here this is why we created
footnote here this is why we created this selector the select all posts
this selector the select all posts because imagine if our the shape of our
because imagine if our the shape of our state had changed and we were referring
state had changed and we were referring to the state directly such as state dot
to the state directly such as state dot posts inside of each component we would
posts inside of each component we would have to go into every one and make that
have to go into every one and make that change but because we used the select
change but because we used the select all posts and exported that now when the
all posts and exported that now when the shape of the state changed we only
shape of the state changed we only needed to change it here inside of the
needed to change it here inside of the slice and now we want to create our
slice and now we want to create our async thunk right here inside of the
async thunk right here inside of the slice file so let's go ahead and import
slice file so let's go ahead and import that at the top and we're currently
that at the top and we're currently importing create slice and nano id so
importing create slice and nano id so now let's add
now let's add create
create async thunk right there for an import
async thunk right there for an import and i also want to define a base url
and i also want to define a base url here so i'm going to put in a posts url
here so i'm going to put in a posts url and then i also want to import axios and
and then i also want to import axios and so let's check our package to see if we
so let's check our package to see if we even have axios i don't think we do yet
even have axios i don't think we do yet so we may need to add that dependency no
so we may need to add that dependency no we don't have axios yet so let's control
we don't have axios yet so let's control backtick and say npm
backtick and say npm i
i axios and install the axios dependency
axios and install the axios dependency so we can use it inside of our async
so we can use it inside of our async thunk
thunk it installed very quickly we now have
it installed very quickly we now have axios here inside of our dependencies in
axios here inside of our dependencies in the package json i'll go back to the
the package json i'll go back to the post slice and let's also
post slice and let's also import
import axios okay with that import complete i'm
axios okay with that import complete i'm just going to put a space there between
just going to put a space there between the imports and the definition of our
the imports and the definition of our post url i'm now going to show you
post url i'm now going to show you the async thunk that we are creating
the async thunk that we are creating here and it is fetch post so i just
here and it is fetch post so i just pasted that in
pasted that in and let's break this down now so here is
and let's break this down now so here is fetch posts and it uses create async
fetch posts and it uses create async thunk now create async thunk accepts two
thunk now create async thunk accepts two arguments so the first one is a string
arguments so the first one is a string that's used as the prefix for the
that's used as the prefix for the generated action type the second is a
generated action type the second is a payload creator callback and this
payload creator callback and this function should return a promise that
function should return a promise that contains some data or rejected promise
contains some data or rejected promise with an error and you can see inside the
with an error and you can see inside the callback which is async we are using
callback which is async we are using axios in a try catch block so we are
axios in a try catch block so we are requesting information from the post url
requesting information from the post url and then we're getting that response
and then we're getting that response data and i'm just spreading it into a
data and i'm just spreading it into a new array right here and then of course
new array right here and then of course we have a catch which could be an error
we have a catch which could be an error message that we return as well and note
message that we return as well and note that we are getting our data from
that we are getting our data from jsonplaceholder.typeycode.com
posts and this is a nice fake api that does accept post requests and get
does accept post requests and get requests and so we'll be able to send
requests and so we'll be able to send data to it and get a response as well so
data to it and get a response as well so it just kind of helps us develop this
it just kind of helps us develop this application now in our post slice we
application now in our post slice we have a reducer here where we have
have a reducer here where we have created the slice and here's the
created the slice and here's the reducers but sometimes a slice reducer
reducers but sometimes a slice reducer needs to respond to other actions that
needs to respond to other actions that weren't defined as part of the slice's
weren't defined as part of the slice's reducers and that is kind of like what
reducers and that is kind of like what happens here with our async thunk fetch
happens here with our async thunk fetch post so let's go ahead and add an extra
post so let's go ahead and add an extra reducers function that is supported so
reducers function that is supported so we can put a comma here and after that
we can put a comma here and after that we say extra reducers and this accepts a
we say extra reducers and this accepts a builder parameter
builder parameter and this builder parameter is an object
and this builder parameter is an object that lets us define additional case
that lets us define additional case reducers that run in response to the
reducers that run in response to the actions defined outside of the slice so
actions defined outside of the slice so i'm going to paste this in and then
i'm going to paste this in and then we'll break it down i'll probably need
we'll break it down i'll probably need to scroll just a little bit actually it
to scroll just a little bit actually it fills more than the screen so we'll
fills more than the screen so we'll break it down bit by bit so here the
break it down bit by bit so here the cases are listening for the promise
cases are listening for the promise status action types that are dispatched
status action types that are dispatched by the fetch posts thunk and then we
by the fetch posts thunk and then we respond by setting our state accordingly
respond by setting our state accordingly so let's look at each one a promise
so let's look at each one a promise could be pending so then we respond by
could be pending so then we respond by setting our status to loading and then a
setting our status to loading and then a promise of course could be fulfilled and
promise of course could be fulfilled and if that's the case we set the status to
if that's the case we set the status to succeeded but then we're also going
succeeded but then we're also going ahead and returning some information
ahead and returning some information here so what we're doing is saying let
here so what we're doing is saying let one minute we're defining this minute
one minute we're defining this minute variable
variable then we're looking at the loaded posts
then we're looking at the loaded posts that we get from the action payload and
that we get from the action payload and we map over each one of those because
we map over each one of those because our fake api doesn't have a couple of
our fake api doesn't have a couple of the areas of data that we need and one
the areas of data that we need and one was the date that we were using so we're
was the date that we were using so we're just
just setting the date with the sub function
setting the date with the sub function from date fns that we had previously
from date fns that we had previously imported and we're increasing the
imported and we're increasing the minutes for each post and that way they
minutes for each post and that way they don't have the same time ago set or time
don't have the same time ago set or time stamp
stamp and then we also have reactions and
and then we also have reactions and those aren't coming from the api either
those aren't coming from the api either so i just needed to add those here and
so i just needed to add those here and then we return that post but essentially
then we return that post but essentially we get the loaded posts from the action
we get the loaded posts from the action payload and then we once again add those
payload and then we once again add those loaded posts to our state and here's the
loaded posts to our state and here's the state.post.concat
state.post.concat now also realize this is still inside
now also realize this is still inside the slice which uses immer js underneath
the slice which uses immer js underneath the hood or in the background so we're
the hood or in the background so we're doing things like concat and like adding
doing things like concat and like adding minutes here that we wouldn't normally
minutes here that we wouldn't normally do because it would mutate the state but
do because it would mutate the state but inside of the create slice with imr.js
inside of the create slice with imr.js that is how we do it and then immerjs
that is how we do it and then immerjs handles it and makes sure it is not a
handles it and makes sure it is not a mutation then of course we also have the
mutation then of course we also have the rejected possibility here and then we
rejected possibility here and then we would set the status to failed and set
would set the status to failed and set our error message so this looks a little
our error message so this looks a little like a switch case statement but it's
like a switch case statement but it's based on the builder and then we have an
based on the builder and then we have an dot add case for each one of these
dot add case for each one of these possibilities here and this is all
possibilities here and this is all inside of the extra reducers so it's
inside of the extra reducers so it's handling something that did not get
handling something that did not get defined inside of the normal reducers
defined inside of the normal reducers part of the slice and now we need to
part of the slice and now we need to save and move on to the posts list
save and move on to the posts list component okay inside of post lists we
component okay inside of post lists we need to go ahead and add to our imports
need to go ahead and add to our imports so we not only have use selector we also
so we not only have use selector we also want use
want use dispatch here
dispatch here and after use dispatch we also need to
and after use dispatch we also need to go ahead and import use effect from
go ahead and import use effect from react so let's add that as well
react so let's add that as well there it is let me tab down there we go
there it is let me tab down there we go and now i've added a space here because
and now i've added a space here because we're going to change some things here
we're going to change some things here but i also realized something besides
but i also realized something besides select all posts let's go ahead and add
select all posts let's go ahead and add some other selectors for our state so
some other selectors for our state so back in the post slice if we scroll back
back in the post slice if we scroll back up and look at our state we also had the
up and look at our state we also had the status and the error so let's add
status and the error so let's add selectors for those as well so we can
selectors for those as well so we can pull all of those in so here after the
pull all of those in so here after the select all posts i'm just going to press
select all posts i'm just going to press shift alt and the down arrow and it's
shift alt and the down arrow and it's going to duplicate that on two other
going to duplicate that on two other lines let's call this one
lines let's call this one get
get posts
posts status and so this would be state dot
status and so this would be state dot posts dot
posts dot status
status and then the next one we'll call git
and then the next one we'll call git posts
posts error
error and this would be state dot posts
and this would be state dot posts air and now we can import those as well
air and now we can import those as well so let's go back to the post list
so let's go back to the post list and after select all posts we're also
and after select all posts we're also going to have
going to have get posts
get posts status
status get
get posts error and we can't forget
posts error and we can't forget our fetch posts when it was created in
our fetch posts when it was created in the slice it was an export cost so we
the slice it was an export cost so we just had it listed above where it's
just had it listed above where it's created just like we have an export cost
created just like we have an export cost here it was just defined above the slice
here it was just defined above the slice so we can also export that so back in
so we can also export that so back in the post list we are now importing
the post list we are now importing select all posts get post status get
select all posts get post status get post error and fetch posts let me hide
post error and fetch posts let me hide the file tree so we can see all of that
the file tree so we can see all of that we've also got use effect from react and
we've also got use effect from react and then use selector and use dispatch from
then use selector and use dispatch from react redux okay let's move inside the
react redux okay let's move inside the post list component now and the first
post list component now and the first thing we'll do is define dispatch so
thing we'll do is define dispatch so we'll say const
we'll say const dispatch we'll set that equal to use
dispatch we'll set that equal to use dispatch
dispatch after that we're going to work with our
after that we're going to work with our selectors here so we have posts already
selectors here so we have posts already let's go ahead and copy this down
let's go ahead and copy this down and so besides posts we're also going to
and so besides posts we're also going to have posts
have posts status and we'll set this equal to the
status and we'll set this equal to the get post status
get post status of course inside of the use selector
of course inside of the use selector and i need an s there to make it look
and i need an s there to make it look right there we go and then we'll also
right there we go and then we'll also have a possible error i didn't get that
have a possible error i didn't get that selected there we go so we'll just set
selected there we go so we'll just set error
error equal to
equal to get
get posts
posts error and now of course they've turned
error and now of course they've turned the proper colors because we're matching
the proper colors because we're matching up with what we imported above now after
up with what we imported above now after these selectors i'm going to go ahead
these selectors i'm going to go ahead and paste in the use effect i'll save to
and paste in the use effect i'll save to get some proper formatting
get some proper formatting but let's look at this use effect so
but let's look at this use effect so we're checking the post status and we're
we're checking the post status and we're seeing if it is idle and then if it's
seeing if it is idle and then if it's idle we're dispatching the fetch posts
idle we're dispatching the fetch posts async thunk so here inside of the
async thunk so here inside of the dependency you can see we're checking
dependency you can see we're checking post status and we have the dispatch
post status and we have the dispatch also listed because those are defined
also listed because those are defined here inside of the component now we're
here inside of the component now we're using fetch posts here but that's
using fetch posts here but that's imported above so we don't need to worry
imported above so we don't need to worry about putting that there and now we want
about putting that there and now we want to display the loading state in our post
to display the loading state in our post list and we're going to start by
list and we're going to start by extracting some of the post list
extracting some of the post list component into a separate component
component into a separate component called posts excerpt so i'll go to the
called posts excerpt so i'll go to the file tree and just inside of our posts
file tree and just inside of our posts directory here we can create a new file
directory here we can create a new file this is going to be called posts
this is going to be called posts excerpt
excerpt dot js and then inside of this i can
dot js and then inside of this i can type r-a-f-c-e
type r-a-f-c-e press tab and we get our post excerpt
press tab and we get our post excerpt component now it's going to receive a
component now it's going to receive a post so i don't want to forget to add
post so i don't want to forget to add that right away but now let's look at
that right away but now let's look at the imports its needs and back inside of
the imports its needs and back inside of posts list
posts list we can just see what we need right here
we can just see what we need right here these three so we did have those in this
these three so we did have those in this component i'm going to press control x
component i'm going to press control x to cut those out and put them instead at
to cut those out and put them instead at the top of posts excerpt so i'll just
the top of posts excerpt so i'll just paste those in and leave a line and it
paste those in and leave a line and it looks like i left a line at the top
looks like i left a line at the top there we go and now if i jump back to
there we go and now if i jump back to the posts list and i scroll down we can
the posts list and i scroll down we can just grab this article that we have here
just grab this article that we have here inside of our rendered post definition
inside of our rendered post definition where we were mapping through the
where we were mapping through the ordered posts once again press control x
ordered posts once again press control x to just pull those out of the post list
to just pull those out of the post list and we can replace this div here that is
and we can replace this div here that is by default and paste in our article and
by default and paste in our article and save there is one short change we need
save there is one short change we need to make and we will not be putting the
to make and we will not be putting the key right here this will go
key right here this will go inside of where we placed the component
inside of where we placed the component in post list so i removed the key from
in post list so i removed the key from the article and we can save this
the article and we can save this component and now we can import it into
component and now we can import it into post list so we'll switch back here
post list so we'll switch back here scroll back to the top
scroll back to the top and we should be able to
and we should be able to import posts
import posts excerpt there it is in the list
excerpt there it is in the list press tab and we now have it where we
press tab and we now have it where we can use it inside of the post list
can use it inside of the post list component and now let's change some of
component and now let's change some of our logic here inside of post list so we
our logic here inside of post list so we can actually display
can actually display the is loading state if we need to i'll
the is loading state if we need to i'll press ctrl b to hide that file tree so
press ctrl b to hide that file tree so we're looking at the order posts and
we're looking at the order posts and rendered posts here and i'm just going
rendered posts here and i'm just going to replace both of these and i will
to replace both of these and i will paste in the new code and then we'll
paste in the new code and then we'll take a look at that now let's go ahead
take a look at that now let's go ahead and remove the problem code that we see
and remove the problem code that we see here as well
here as well and let's see what we've got we've got
and let's see what we've got we've got let content so we've got a content
let content so we've got a content variable to start out with
variable to start out with which we're defining as we go through
which we're defining as we go through this if else if else if logical
this if else if else if logical conditional here so we're checking the
conditional here so we're checking the post status and if it is loading then
post status and if it is loading then we're just going to say loading and if
we're just going to say loading and if you had a spinner component this would
you had a spinner component this would be a good place for it as well
be a good place for it as well else if our post status has succeeded
else if our post status has succeeded then we're going to define the order
then we're going to define the order post that we had before and this looks
post that we had before and this looks much the same where we sort them based
much the same where we sort them based on the date and then we set our content
on the date and then we set our content equal to the ordered post that we're
equal to the ordered post that we're going to map over
going to map over and now here is our new posts excerpt
and now here is our new posts excerpt component and you can see i'm now
component and you can see i'm now providing the key here as we go through
providing the key here as we go through the map and then of course use the
the map and then of course use the component for each different post that
component for each different post that we have and we're also passing in the
we have and we're also passing in the post that that component receives and
post that that component receives and our final one of course is the failed
our final one of course is the failed status and then we set the content to
status and then we set the content to the error so that can be displayed and
the error so that can be displayed and because of this change we also need to
because of this change we also need to change rendered posts now to our content
change rendered posts now to our content variable inside the jsx and this seems
variable inside the jsx and this seems like it would be a good time to test out
like it would be a good time to test out our application so i'm going to press
our application so i'm going to press ctrl backtick type npm start
ctrl backtick type npm start and fire up react now i'm going to pull
and fire up react now i'm going to pull visual studio code over to the left as
visual studio code over to the left as this works and we should see our react
this works and we should see our react app here on the right as soon as the
app here on the right as soon as the development server gets it up and
development server gets it up and running and as i often times do i have
running and as i often times do i have an error it looks like we're referring
an error it looks like we're referring to post status here and i bet i put post
to post status here and i bet i put post status with an extra s up above and i
status with an extra s up above and i sure did so we could change all of those
sure did so we could change all of those or we could just change this one here so
or we could just change this one here so what i will do is just make that post
what i will do is just make that post status and save and now we should see
status and save and now we should see our application instead we've got a
our application instead we've got a blank page so let's check out what's
blank page so let's check out what's going on here by looking at the devtools
going on here by looking at the devtools shift control i
shift control i and yes we definitely have an error
and yes we definitely have an error let's see what it is
let's see what it is we are not reading undefined so
we are not reading undefined so something is going wrong let's look here
something is going wrong let's look here it occurred in post excerpt
it occurred in post excerpt and so there is an issue at least with
and so there is an issue at least with the content so let's look at the sub
the content so let's look at the sub string we're referencing in the post
string we're referencing in the post excerpt
excerpt i'll grab this drag it back to the right
i'll grab this drag it back to the right we go to the post excerpt component
we go to the post excerpt component and here's substring and i see it's
and here's substring and i see it's referencing content
referencing content but our api delivers the content in the
but our api delivers the content in the post dot body so if i save that
post dot body so if i save that we should be good and we are so now we
we should be good and we are so now we have our form here at the top as we
have our form here at the top as we created in part two of this tutorial
created in part two of this tutorial series but let's look at all of these
series but let's look at all of these posts that we're bringing in
posts that we're bringing in and they have lorem epsom from the json
and they have lorem epsom from the json typey code website or jsonplaceholder
typey code website or jsonplaceholder website
website and we can see we're getting
and we can see we're getting lots and lots of posts we should
lots and lots of posts we should actually have a hundred if i were to
actually have a hundred if i were to scroll here
scroll here through all of these so yeah we've got
through all of these so yeah we've got all the posts and everything is coming
all the posts and everything is coming in as we expect it to but there is one
in as we expect it to but there is one thing about these posts they have
thing about these posts they have unknown authors so right now we also
unknown authors so right now we also want to go ahead and grab the users from
want to go ahead and grab the users from the api so it matches up to the posts
the api so it matches up to the posts and then our posts will actually have
and then our posts will actually have authors instead of unknown authors i'll
authors instead of unknown authors i'll leave our react app running here to the
leave our react app running here to the right but i'm going to go ahead and pull
right but i'm going to go ahead and pull visual studio code over so it takes up
visual studio code over so it takes up the full screen again we'll follow a
the full screen again we'll follow a very similar pattern that we did with
very similar pattern that we did with the post slice but now let's go to the
the post slice but now let's go to the file tree
file tree and collapse the posts and go into users
and collapse the posts and go into users and select the user slice we'll want to
and select the user slice we'll want to import or create async thunk again so we
import or create async thunk again so we have create async thunk
have create async thunk after that we're also going to want to
after that we're also going to want to import axios which we do now have as a
import axios which we do now have as a dependency already
dependency already so there is our axios and after that
so there is our axios and after that we're going to want to define a url
we're going to want to define a url again and i'll just paste that in this
again and i'll just paste that in this is our user's url it comes from the same
is our user's url it comes from the same api but it is slash users and yes we
api but it is slash users and yes we could create an axios instance and set a
could create an axios instance and set a base url and then import that as well i
base url and then import that as well i did not do that for this tutorial but
did not do that for this tutorial but it's something you absolutely could do
it's something you absolutely could do we're going to set the initial state now
we're going to set the initial state now remove our static state and just set it
remove our static state and just set it to an empty array as well and now i'm
to an empty array as well and now i'm going to paste in our async thunk and it
going to paste in our async thunk and it is much like our fetch post was so i'll
is much like our fetch post was so i'll hide the file tree so we can get a
hide the file tree so we can get a better look but we've got fetch users
better look but we've got fetch users instead of fetch posts
instead of fetch posts once again create async thunk it has
once again create async thunk it has this description here to start out with
this description here to start out with that follows the same pattern we named
that follows the same pattern we named the slice and then we named the function
the slice and then we named the function and then here's the callback and once
and then here's the callback and once again we're getting the users i'm
again we're getting the users i'm returning the response data inside of a
returning the response data inside of a new array
new array and it returns an error message if we
and it returns an error message if we get that all inside of a try catch block
get that all inside of a try catch block so
so very very close to our fetch posts async
very very close to our fetch posts async thunk
thunk and because it is an async thunk and
and because it is an async thunk and happens outside of the slice we once
happens outside of the slice we once again
again need to supply something
need to supply something inside of the slice to handle that and
inside of the slice to handle that and that is the extra reducer section so
that is the extra reducer section so i'll paste that in and save and we can
i'll paste that in and save and we can see it once again receives a builder in
see it once again receives a builder in this instance we're only looking for one
this instance we're only looking for one case so our add case is looking for
case so our add case is looking for fetch users dot fulfilled and then of
fetch users dot fulfilled and then of course the action is the action payload
course the action is the action payload and here we're returning the action
and here we're returning the action payload and that means it replaces the
payload and that means it replaces the user state completely it was an empty
user state completely it was an empty array of course but we could have used
array of course but we could have used something like state dot push and then
something like state dot push and then spread in this payload and that would be
spread in this payload and that would be something that mr.js would also handle
something that mr.js would also handle but by returning the payload without the
but by returning the payload without the push at all that means we are completely
push at all that means we are completely overriding the state and it also means
overriding the state and it also means we're not going to accidentally add in
we're not going to accidentally add in the users twice or something like that
the users twice or something like that so we're just returning the full action
so we're just returning the full action payload here and now we want to dispatch
payload here and now we want to dispatch our fetch users async thunk and this is
our fetch users async thunk and this is going to be a little different than we
going to be a little different than we did before so let's go to the file tree
did before so let's go to the file tree and we actually want to go directly to
and we actually want to go directly to the index.js
the index.js and that is because we want to load the
and that is because we want to load the users right when the app starts so what
users right when the app starts so what we can do is first
we can do is first import our
import our fetch users there it is
fetch users there it is and after we get that of course it's
and after we get that of course it's going to come from
going to come from dot features
dot features and then slash users slash
and then slash users slash user slice there we go
user slice there we go and then we're going to just say store
and then we're going to just say store dot dispatch and
dot dispatch and then call fetch users we want this
then call fetch users we want this immediately when the application loads
immediately when the application loads and we can do this because we have
and we can do this because we have access to the store right there okay
access to the store right there okay with these changes saved let's drag
with these changes saved let's drag visual studio code back to the left and
visual studio code back to the left and now let's look at our application and
now let's look at our application and you can see we now have leanne graham
you can see we now have leanne graham listed here as an author instead of an
listed here as an author instead of an unknown author and leanne should be the
unknown author and leanne should be the author for the first 10 posts and then
author for the first 10 posts and then it should switch to another author so
it should switch to another author so i'll scroll down yes our next author is
i'll scroll down yes our next author is ervin howell of course the way this api
ervin howell of course the way this api data works he'll have the next 10 posts
data works he'll have the next 10 posts and so on but we should have 10
and so on but we should have 10 different authors and we should be able
different authors and we should be able to see those authors now in our drop
to see those authors now in our drop down list here for author so yes we do
down list here for author so yes we do there they all are we have the different
there they all are we have the different authors listed from the api
authors listed from the api so now our last adjustment to this
so now our last adjustment to this project is to change how we add a new
project is to change how we add a new post so to do that let's go back to
post so to do that let's go back to visual studio code i'll make it take up
visual studio code i'll make it take up the full window once again we need to go
the full window once again we need to go back to the post slice
back to the post slice and handle new posts now as you might
and handle new posts now as you might guess inside the post slice this is
guess inside the post slice this is going to take a new async thunk so i'll
going to take a new async thunk so i'll paste it right below our fetch posts and
paste it right below our fetch posts and we can break it down wait a minute there
we can break it down wait a minute there we go and i'll save and i'll press ctrl
we go and i'll save and i'll press ctrl b to hide the file tree again let's look
b to hide the file tree again let's look at our new async thunk here called add
at our new async thunk here called add new post so once again it's named post
new post so once again it's named post slash add new post
slash add new post here is the async callback notice it
here is the async callback notice it receives initial post data and so this
receives initial post data and so this will be the body of the post request
will be the body of the post request that we send to axios and then we once
that we send to axios and then we once again get that response data now this
again get that response data now this will just be one record and we know that
will just be one record and we know that it will not be an array like we might
it will not be an array like we might have expected when we got all of the
have expected when we got all of the posts and then of course in our builders
posts and then of course in our builders case below under the extra reducers we
case below under the extra reducers we need to add a case for our new post so
need to add a case for our new post so here we have our extra reducers and the
here we have our extra reducers and the builder we have the case for fetch posts
builder we have the case for fetch posts pending fulfilled and also rejected so
pending fulfilled and also rejected so then let's add one more case below
then let's add one more case below and i'll save if we can get proper
and i'll save if we can get proper formatting it would help let me get rid
formatting it would help let me get rid of that space there we go so now we've
of that space there we go so now we've got new post and we're just looking at
got new post and we're just looking at fulfilled again once again
fulfilled again once again since the api does not have some of the
since the api does not have some of the extra data that we've been using i'm
extra data that we've been using i'm adding that here with the date and the
adding that here with the date and the reactions
reactions and i'm even logging to the console the
and i'm even logging to the console the payload so if you want to see that
payload so if you want to see that however we're getting the user id here
however we're getting the user id here and the api provides the user id
and the api provides the user id i believe as a string so we're just
i believe as a string so we're just converting that to number as well
converting that to number as well and then we're pushing that action
and then we're pushing that action payload to the array once again we're
payload to the array once again we're still inside of create slice so
still inside of create slice so emerge.js is under the hood and we can
emerge.js is under the hood and we can use push here like would normally mutate
use push here like would normally mutate state but remember emerges handles that
state but remember emerges handles that underneath and it will not so this is
underneath and it will not so this is the correct way to do this inside of the
the correct way to do this inside of the create slice only so now let's save the
create slice only so now let's save the slice and go back to the file tree
slice and go back to the file tree because we need to go to our add post
because we need to go to our add post form component i'll press ctrl b again
form component i'll press ctrl b again to hide the file tree and we need to
to hide the file tree and we need to replace our post added that we are
replace our post added that we are importing with our add
importing with our add new post thunk that we created let's
new post thunk that we created let's also add some extra state where we're
also add some extra state where we're going to look at the state or the status
going to look at the state or the status actually so add request status and set
actually so add request status and set add request status and we'll start that
add request status and we'll start that out as idle and now that we have that
out as idle and now that we have that new state to work with let's scroll down
new state to work with let's scroll down i believe underneath the on save post
i believe underneath the on save post click yes we've got this can save
click yes we've got this can save variable let's put this above so i'm
variable let's put this above so i'm just going to press control x and then
just going to press control x and then come up here above the on save post
come up here above the on save post clicked function
clicked function and there we'll put our can save because
and there we'll put our can save because we're going to change it a little bit so
we're going to change it a little bit so right now we're checking to see if the
right now we're checking to see if the title the content and the user id
title the content and the user id are true before the button can be
are true before the button can be clicked on the form let's refactor this
clicked on the form let's refactor this so it looks just a little different and
so it looks just a little different and will also take into account our request
will also take into account our request status so i will paste this
status so i will paste this over to change it and now you can see
over to change it and now you can see we're still checking the title content
we're still checking the title content and user id but we've put them in an
and user id but we've put them in an array and we're using every and then
array and we're using every and then passing them bully in there so once
passing them bully in there so once again it is just checking to see if all
again it is just checking to see if all of these are true
of these are true but it is refactored and i kind of like
but it is refactored and i kind of like how that looks after that we've got the
how that looks after that we've got the double ampersand so then we're also
double ampersand so then we're also checking to make sure that the add
checking to make sure that the add request status state is idle before we
request status state is idle before we can click the can save or the save
can click the can save or the save button and this is just verifying that
button and this is just verifying that we can save and now let's scroll up just
we can save and now let's scroll up just a little bit we're going to change the
a little bit we're going to change the body of our on save post click so i'll
body of our on save post click so i'll just highlight what's inside
just highlight what's inside and paste this in and we'll break it
and paste this in and we'll break it down so we are
down so we are checking the status now of can save as
checking the status now of can save as well then we have a try
well then we have a try catch
catch finally so we start out by setting our
finally so we start out by setting our request status depending instead of idle
request status depending instead of idle and at the end in the finally no matter
and at the end in the finally no matter if there's an error or not it is always
if there's an error or not it is always going to set it back to idle so that
going to set it back to idle so that helps us work with our button there and
helps us work with our button there and then of course we're calling dispatch
then of course we're calling dispatch here and dispatching the add new post
here and dispatching the add new post thunk that we created and we're passing
thunk that we created and we're passing in the title and here we have the body
in the title and here we have the body and then that is the content and then
and then that is the content and then the user id redux toolkit adds an unwrap
the user id redux toolkit adds an unwrap function to the returned promise and
function to the returned promise and then that returns a new promise that
then that returns a new promise that either has the action payload or it
either has the action payload or it throws an error if it's the rejected
throws an error if it's the rejected action so that lets us use this
action so that lets us use this tri-catch logic here so it will throw an
tri-catch logic here so it will throw an error if it is rejected and then we're
error if it is rejected and then we're just emptying out our state as we were
just emptying out our state as we were before after this process is complete so
before after this process is complete so now we can save this form and we should
now we can save this form and we should be finished let's test out the app once
be finished let's test out the app once again
again and we can try to add a new post so
and we can try to add a new post so i'll just say
i'll just say hey there and let's attribute this to
hey there and let's attribute this to leanne and we'll just say
leanne and we'll just say hey there
hey there hello
hello and we save and we've of course sorted
and we save and we've of course sorted in reverse order so our new post is the
in reverse order so our new post is the first one here it's from leanne graham
first one here it's from leanne graham and there's the new post and we still
and there's the new post and we still have all the other posts as well
have all the other posts as well so now we have taken this project and
so now we have taken this project and made it interact with an api to not only
made it interact with an api to not only retrieve data but to post new data using
retrieve data but to post new data using async thunks to complete asynchronous
async thunks to complete asynchronous actions with redux
actions with redux a quick correction sometimes i get to
a quick correction sometimes i get to the end of making a video and notice a
the end of making a video and notice a mistake this is a small one but i do
mistake this is a small one but i do want to fix it we didn't do anything
want to fix it we didn't do anything with the emojis today so i really didn't
with the emojis today so i really didn't notice they were off but notice we don't
notice they were off but notice we don't even have a number by each emoji so if i
even have a number by each emoji so if i click coffee it gives me the not a
click coffee it gives me the not a number so i knew something was up once i
number so i knew something was up once i discovered this what we want to do is
discovered this what we want to do is just go into the post slice and i just
just go into the post slice and i just put in the wrong names when i put in the
put in the wrong names when i put in the new reducer so here are the correct
new reducer so here are the correct names we have thumbs up wow heart rocket
names we have thumbs up wow heart rocket and coffee let me just copy those with
and coffee let me just copy those with the zeros here
the zeros here and in the extra reducers now for our
and in the extra reducers now for our async thunk we want to replace these
async thunk we want to replace these where there's the hooray and the eyes
where there's the hooray and the eyes and just some different ones that we
and just some different ones that we didn't have so if i highlight those
didn't have so if i highlight those save
save and then of course we're going to reload
and then of course we're going to reload our application
our application and now we have a zero by each emoji and
and now we have a zero by each emoji and they'll all continue to count correctly
they'll all continue to count correctly so what was missing were the correct
so what was missing were the correct reaction names inside of our
reaction names inside of our add case for the fetch post dot
add case for the fetch post dot fulfilled in the extra reducers just a
fulfilled in the extra reducers just a quick correction there everything else
quick correction there everything else seems good let's build a blog app as an
seems good let's build a blog app as an example react and redux toolkit project
example react and redux toolkit project and our blog project will support all
and our blog project will support all crud operations when we create read
crud operations when we create read update and delete blog posts we're going
update and delete blog posts we're going to jump right in where we left off in
to jump right in where we left off in part three of this redux toolkit series
part three of this redux toolkit series and we created an example bulletin board
and we created an example bulletin board project in reacts with redux toolkit and
project in reacts with redux toolkit and today we're going to refactor this
today we're going to refactor this single page application into a
single page application into a multi-page blog and you can download the
multi-page blog and you can download the starter code that i'm starting with from
starter code that i'm starting with from the sources in the description okay
the sources in the description okay we're here at the app js and you can see
we're here at the app js and you can see we've just got this single page
we've just got this single page application we're pulling in an ad post
application we're pulling in an ad post form component and a post list component
form component and a post list component and they all display at the same time if
and they all display at the same time if you run the code right now the form is
you run the code right now the form is on top and then the post list is just
on top and then the post list is just underneath so it's really a bulletin
underneath so it's really a bulletin board
board single page application we're going to
single page application we're going to change this into a multi-page blog and
change this into a multi-page blog and we're going to start by adding a single
we're going to start by adding a single page that we can view just one post at a
page that we can view just one post at a time and view the full page and not an
time and view the full page and not an excerpt but the entire post i should say
excerpt but the entire post i should say the full post so what we want to do
the full post so what we want to do is first go into the post slice that's
is first go into the post slice that's in our features directory and here we're
in our features directory and here we're going to add a selector to select a post
going to add a selector to select a post by id we've already created some
by id we've already created some selectors at the bottom so let's go see
selectors at the bottom so let's go see those so down here at the bottom of the
those so down here at the bottom of the post sliced we have select all posts
post sliced we have select all posts get post status and get posts error and
get post status and get posts error and you can see they're very simple they
you can see they're very simple they receive the state and then they either
receive the state and then they either return all the posts the status or the
return all the posts the status or the error that we have in the initial state
error that we have in the initial state where we set that up and that's way up
where we set that up and that's way up above if i scroll back up here's the
above if i scroll back up here's the initial state with post status and error
initial state with post status and error but now we want to just get one single
but now we want to just get one single post and we'll do that with the post id
post and we'll do that with the post id so i'm going to grab that quickly and
so i'm going to grab that quickly and paste it in and we'll review so right
paste it in and we'll review so right underneath i'm pasting in this new
underneath i'm pasting in this new selector and you can see select post by
selector and you can see select post by id it receives not only the state but a
id it receives not only the state but a post id
post id and then once again we're referring to
and then once again we're referring to the posts and yes it's state dot posts
the posts and yes it's state dot posts dot posts here but we are finding then
dot posts here but we are finding then the post by the post id where they match
the post by the post id where they match okay we're exporting the selector as
okay we're exporting the selector as well so i'm going to save this page and
well so i'm going to save this page and now still in the posts directory here
now still in the posts directory here that's in the features directory which
that's in the features directory which is in the source directory so here we
is in the source directory so here we are at posts i'm going to create a new
are at posts i'm going to create a new component so i'm going to hit the new
component so i'm going to hit the new icon up there and we'll call this
icon up there and we'll call this single
single post
post page dot js now this is going to let us
page dot js now this is going to let us view the full post and it's going to
view the full post and it's going to look a lot like our posts excerpt
look a lot like our posts excerpt component that we have here but notice
component that we have here but notice we're only viewing the first 100
we're only viewing the first 100 characters right now and we're passing
characters right now and we're passing in the post this is going to get the
in the post this is going to get the post in a different way using that
post in a different way using that selector so let's go back to the single
selector so let's go back to the single page post i'm going to paste this in and
page post i'm going to paste this in and we can review so i will scroll to the
we can review so i will scroll to the top notice we're importing in use
top notice we're importing in use selector and then we're importing in the
selector and then we're importing in the selector that we just created we also
selector that we just created we also have the post author time ago and
have the post author time ago and reaction buttons related to the post as
reaction buttons related to the post as well because that will let us view those
well because that will let us view those now i've made a comment here because we
now i've made a comment here because we haven't retrieved the post id yet we're
haven't retrieved the post id yet we're going to do that soon as we implement
going to do that soon as we implement react router and we'll get it from a
react router and we'll get it from a parameter but right now if we had the
parameter but right now if we had the post
post then we're going to go ahead or at least
then we're going to go ahead or at least the post id if we had the post id then
the post id if we had the post id then we're going to go ahead and use our
we're going to go ahead and use our selector and pass in the post id now
selector and pass in the post id now this selector is different because it
this selector is different because it accepts the two parameters state and the
accepts the two parameters state and the post id so notice we're not just passing
post id so notice we're not just passing in
in our selector by name we actually need to
our selector by name we actually need to have an anonymous function here that
have an anonymous function here that passes in the state and then we can pass
passes in the state and then we can pass in the state as well as the post id to
in the state as well as the post id to the selector here after this if the post
the selector here after this if the post is not found we're going to return a
is not found we're going to return a section element with an h2 that simply
section element with an h2 that simply says post not found however if it is
says post not found however if it is found then we're going to return the
found then we're going to return the post and it looks much like the post
post and it looks much like the post excerpt except it's not limited to the
excerpt except it's not limited to the first hundred characters it will be the
first hundred characters it will be the full post with that complete i'll save
full post with that complete i'll save this file and now i'm going to press
this file and now i'm going to press ctrl and the back tick
ctrl and the back tick and we'll also scroll down here and pull
and we'll also scroll down here and pull up our package.json so we can see our
up our package.json so we can see our dependencies
dependencies and we see in our dependencies right
and we see in our dependencies right here that we do not currently have react
here that we do not currently have react router and we're going to need that for
router and we're going to need that for a multi-page blog so we need to type in
a multi-page blog so we need to type in npm
npm i
i and then react dash router dash dom
and then react dash router dash dom press enter it should install quickly
press enter it should install quickly and then we'll verify that it's listed
and then we'll verify that it's listed in our dependencies all right the
in our dependencies all right the install is already complete and we now
install is already complete and we now have react router dom 6.3 as of the
have react router dom 6.3 as of the making of this tutorial listed in our
making of this tutorial listed in our dependencies so i will go ahead and
dependencies so i will go ahead and close out of the terminal and close out
close out of the terminal and close out of the package json now let's go to the
of the package json now let's go to the index.js and implement the react router
index.js and implement the react router now i do have a specific tutorial for
now i do have a specific tutorial for react router version 6. so if you're not
react router version 6. so if you're not familiar with that now would be a good
familiar with that now would be a good time to pause or just go over to my
time to pause or just go over to my channel and find that i'll probably link
channel and find that i'll probably link to it in the description below as well
to it in the description below as well but the purpose is i'm not going to just
but the purpose is i'm not going to just be teaching react router here you'll see
be teaching react router here you'll see how it's implemented but i'm not going
how it's implemented but i'm not going to slow down just to go over the basics
to slow down just to go over the basics of react router so here we're going to
of react router so here we're going to import in several things for react
import in several things for react router we've got
router we've got browser router as router so we renamed
browser router as router so we renamed that then we've got routes and a
that then we've got routes and a singular route as well now notice in the
singular route as well now notice in the jsx we've got react strict mode which
jsx we've got react strict mode which you could review uh remove you don't
you could review uh remove you don't have to have strict mode if you don't
have to have strict mode if you don't want to then we've got the provider and
want to then we've got the provider and then just the app so we're going to
then just the app so we're going to replace just the app here with
replace just the app here with everything else the provider can
everything else the provider can surround what we're going to do with the
surround what we're going to do with the router because we want to provide the
router because we want to provide the store to the entire application so i'll
store to the entire application so i'll just paste the rest of this in and we
just paste the rest of this in and we can see the changes when i save it gets
can see the changes when i save it gets formatted correctly so we start with
formatted correctly so we start with router and that is browser router and we
router and that is browser router and we named it router here then we have routes
named it router here then we have routes and then we have a single route now this
and then we have a single route now this path is important because the slash and
path is important because the slash and the asterisk will allow for nested
the asterisk will allow for nested routes when we get to our app app.js and
routes when we get to our app app.js and then for the element attribute we just
then for the element attribute we just pass in the app component and so that's
pass in the app component and so that's all we need to do in index so let's save
all we need to do in index so let's save this and move to the app.js file and
this and move to the app.js file and really before we make any changes in the
really before we make any changes in the app.js file i'm going to scroll up
app.js file i'm going to scroll up collapse the post directory just so we
collapse the post directory just so we can see all of this better and inside of
can see all of this better and inside of the source directory i'm going to create
the source directory i'm going to create a new directory and make a components
a new directory and make a components directory so
directory so this is going to house the components
this is going to house the components that are more for layout and not
that are more for layout and not associated with posts or users
associated with posts or users specifically so inside of this
specifically so inside of this components directory i'm going to create
components directory i'm going to create a new component named
a new component named layout.js this component is rather
layout.js this component is rather simple and this strategy was introduced
simple and this strategy was introduced with react router version 6. we're
with react router version 6. we're creating an outlet layout here so if we
creating an outlet layout here so if we had something like a header or a footer
had something like a header or a footer we would also probably include it here
we would also probably include it here in our layout file right now we don't we
in our layout file right now we don't we may in the future
may in the future but we're using this outlet and this
but we're using this outlet and this outlet represents all of the children so
outlet represents all of the children so when we put the layout component into
when we put the layout component into our application it can then represent
our application it can then represent all of these children underneath so
all of these children underneath so we'll save here and now if we were to
we'll save here and now if we were to have a header or a footer or anything of
have a header or a footer or anything of course they would always appear with all
course they would always appear with all of the children okay now let's go to the
of the children okay now let's go to the app.js file and apply the routing from
app.js file and apply the routing from react router so we have two imports at
react router so we have two imports at the top already we're going to add a few
the top already we're going to add a few more to that so i'll paste those in now
more to that so i'll paste those in now we're importing our single post page
we're importing our single post page we're also importing our layout and then
we're also importing our layout and then we're importing routes and the singular
we're importing routes and the singular route from react router dom now let's
route from react router dom now let's look at the jsx that we're returning and
look at the jsx that we're returning and of course we already abstracted this
of course we already abstracted this main with the class name app to our
main with the class name app to our layout component so we see that right
layout component so we see that right here as well so we don't need that
here as well so we don't need that repeating here inside this what i'm
repeating here inside this what i'm going to do is just highlight all of
going to do is just highlight all of that and paste in the new routing
that and paste in the new routing save and i'll review this with you so we
save and i'll review this with you so we have our routes and what we're defining
have our routes and what we're defining here is the root route essentially the
here is the root route essentially the path with the slash and then we pass in
path with the slash and then we pass in that layout component that we created so
that layout component that we created so it is the parent to everything else here
it is the parent to everything else here now inside of this path we can have an
now inside of this path we can have an index element and so we note that here
index element and so we note that here with the route index and the element and
with the route index and the element and we have post list so that's really what
we have post list so that's really what we want to come up as the home page is
we want to come up as the home page is our post list component and of course
our post list component and of course anything else that was applied in the
anything else that was applied in the layout will also be part of that
layout will also be part of that and then we have another route and that
and then we have another route and that is post so this would be slash post and
is post so this would be slash post and the index for that route so
the index for that route so whatever dot com slash post slash and
whatever dot com slash post slash and then the ad post form so we could add a
then the ad post form so we could add a new post
new post if we went to the slash post route and
if we went to the slash post route and then if we had after the slash post if
then if we had after the slash post if we had another slash we could have the
we had another slash we could have the post id parameter and that would go to
post id parameter and that would go to the single post page and pull up
the single post page and pull up whatever post id parameter was in the
whatever post id parameter was in the url so here we have two nested routes
url so here we have two nested routes that are inside of our home route
that are inside of our home route one is the index and one is the post
one is the index and one is the post route and then the post route has its
route and then the post route has its own index and then of course a route
own index and then of course a route that will support parameters for each
that will support parameters for each individual post okay with the routing
individual post okay with the routing covered let's go back to our single post
covered let's go back to our single post page that we started and we need to
page that we started and we need to allow that page to actually get that
allow that page to actually get that post id so how we're going to do that
post id so how we're going to do that now that we have react router is to go
now that we have react router is to go ahead and import the use params hook
ahead and import the use params hook from react router dom and then once we
from react router dom and then once we have that imported we can apply it here
have that imported we can apply it here inside of the component i'm going to
inside of the component i'm going to select this and i'm going to select the
select this and i'm going to select the use selector here that we are using and
use selector here that we are using and paste over both because there's one
paste over both because there's one change i want to go over with that use
change i want to go over with that use selector i'm going to press ctrl b to
selector i'm going to press ctrl b to hide the file tree for now but here
hide the file tree for now but here we're using the use params hook to get
we're using the use params hook to get the post id so it's going to pull that
the post id so it's going to pull that value from the url parameter
value from the url parameter and then this use selector the change i
and then this use selector the change i made is wrapping the post id
made is wrapping the post id in number so we can actually get that
in number so we can actually get that accurate comparison back in the post
accurate comparison back in the post slice when we were finding the post by
slice when we were finding the post by id because otherwise the string and
id because otherwise the string and number values would not actually have a
number values would not actually have a strict equals and there's one more
strict equals and there's one more change i want to make before we test out
change i want to make before we test out our changes let's go to that post
our changes let's go to that post excerpt component that is much like our
excerpt component that is much like our single post page and here we need to add
single post page and here we need to add a new import from react router we're
a new import from react router we're importing in link from react router dom
importing in link from react router dom and then we're going to change this line
and then we're going to change this line where we have the post.body.substring
where we have the post.body.substring we're going to limit that substring just
we're going to limit that substring just a little more to 75 characters and we
a little more to 75 characters and we applied the class name of excerpt now
applied the class name of excerpt now i'm providing some new css in the index
i'm providing some new css in the index css and you can download that from the
css and you can download that from the resources if you want to or you can just
resources if you want to or you can just apply your own i'm not going over the
apply your own i'm not going over the css today and finally let's go ahead and
css today and finally let's go ahead and add to the post credit class here this
add to the post credit class here this paragraph we have we'll go ahead and use
paragraph we have we'll go ahead and use the link that we imported from react
the link that we imported from react router dom now this creates an anchor
router dom now this creates an anchor tag when the html is rendered but notice
tag when the html is rendered but notice it's linking to
it's linking to the post path and then the post dot id
the post path and then the post dot id so we can view the individual post so
so we can view the individual post so we're just adding a link to each excerpt
we're just adding a link to each excerpt that will allow us to navigate to the
that will allow us to navigate to the full post and now let's save our changes
full post and now let's save our changes and then press ctrl backtick and let's
and then press ctrl backtick and let's test out the application see if we have
test out the application see if we have any errors or if everything is working
any errors or if everything is working as it should so we typed npm start
as it should so we typed npm start and it should start up the server and
and it should start up the server and here we're going to have a new tab
here we're going to have a new tab and our application should start on the
and our application should start on the right very shortly we'll probably tweak
right very shortly we'll probably tweak a little bit of this because it's right
a little bit of this because it's right up against the left side
up against the left side and everything else looks as it should
and everything else looks as it should though we've got posts and each
though we've got posts and each individual post as we come down has its
individual post as we come down has its own view post link let's see if that's
own view post link let's see if that's working as well yes we can go to the
working as well yes we can go to the individual post page as well now we
individual post page as well now we would have to currently use the back
would have to currently use the back button to go back but we will add a
button to go back but we will add a header very soon let's go back to vs
header very soon let's go back to vs code i'll close the terminal but i'll
code i'll close the terminal but i'll just leave the app running and now
just leave the app running and now inside of the components directory let's
inside of the components directory let's add that header component so it's just
add that header component so it's just header.js
header.js i'll paste this in and we can quickly
i'll paste this in and we can quickly look we've got link from react router
look we've got link from react router again because we have a couple of
again because we have a couple of navigation links but this should provide
navigation links but this should provide a header that we can always see no
a header that we can always see no matter what page we navigate to which
matter what page we navigate to which will help us either go back to the home
will help us either go back to the home page which will have the list of post
page which will have the list of post excerpts or go to the post a new post
excerpts or go to the post a new post page essentially a new blog post and of
page essentially a new blog post and of course from the home page we could click
course from the home page we could click on view post that would take us to the
on view post that would take us to the individual post page and that's where
individual post page and that's where we're eventually going to be able to
we're eventually going to be able to either edit or delete the post as well
either edit or delete the post as well so let's save this and now we need to go
so let's save this and now we need to go to the post list component i know we
to the post list component i know we need to go to the layout component and
need to go to the layout component and here at the top we'll just import the
here at the top we'll just import the header so import
header so import header and it's right in the same
header and it's right in the same directory so there it is and now besides
directory so there it is and now besides the outlet
the outlet we're going to actually put the header
we're going to actually put the header above the main element so let's say
above the main element so let's say header and save and what we are missing
header and save and what we are missing is you see the red here is a fragment
is you see the red here is a fragment which would help us out so let's put in
which would help us out so let's put in the
the jsx fragment and then after this last
jsx fragment and then after this last element
element we'll put the closing fragment save and
we'll put the closing fragment save and it should format correctly that looks
it should format correctly that looks more like i want it to now since we
more like i want it to now since we didn't stop the app let's go ahead and
didn't stop the app let's go ahead and see what changes we can see when i drag
see what changes we can see when i drag this over well this looks better it
this over well this looks better it doesn't look great but let's see what it
doesn't look great but let's see what it looks like if we drag it to a full page
looks like if we drag it to a full page now
now and that looks much more like i was
and that looks much more like i was expecting now i think we could remove
expecting now i think we could remove this posts here because it's obvious
this posts here because it's obvious that these are posts and each one says
that these are posts and each one says view post but overall this looks good we
view post but overall this looks good we could maybe refactor or add some more
could maybe refactor or add some more css for a smaller screen but right now
css for a smaller screen but right now let's just drag it back over here and
let's just drag it back over here and let's go to that post list page and see
let's go to that post list page and see if we can remove i'll press ctrl b
if we can remove i'll press ctrl b see if we can remove that h2 that says
see if we can remove that h2 that says posts so yes
posts so yes that looks good
that looks good and we'll save that and now if we also
and we'll save that and now if we also go to the posts excerpt once again
go to the posts excerpt once again those were h3s we could now change those
those were h3s we could now change those to h2s that header hierarchy is
to h2s that header hierarchy is important and we just removed the h2
important and we just removed the h2 so there we go
so there we go and it did change the size a little bit
and it did change the size a little bit we could change our css if we want to
we could change our css if we want to for that but now we have an h1 at the
for that but now we have an h1 at the top of the page and an h2 here for each
top of the page and an h2 here for each additional post
additional post okay let's go back to vs code now i'll
okay let's go back to vs code now i'll drag this back to the full screen and
drag this back to the full screen and once we're in the full screen i'll press
once we're in the full screen i'll press ctrl b to see the file tree again and we
ctrl b to see the file tree again and we want to go back to the single post page
want to go back to the single post page component
component and inside the single post page
and inside the single post page component we want to add a edit button
component we want to add a edit button so we can edit each post so what we want
so we can edit each post so what we want to do first and i've got an extra line
to do first and i've got an extra line here at the top i can remove but we want
here at the top i can remove but we want to import something else from react
to import something else from react router dom and that's going to be link
router dom and that's going to be link from react router dom and now as we
from react router dom and now as we scroll down essentially in the same spot
scroll down essentially in the same spot we put the view post for the excerpt we
we put the view post for the excerpt we can put the edit post here in our single
can put the edit post here in our single post page so now we can save that with
post page so now we can save that with the link added and now just like we have
the link added and now just like we have an ad post form page we're going to
an ad post form page we're going to create another component here that is
create another component here that is going to be
going to be edit post form dot js
edit post form dot js and i'll paste the code in and then
and i'll paste the code in and then we'll review it's really kind of a
we'll review it's really kind of a hybrid between the single post page
hybrid between the single post page because this is just for one post
because this is just for one post and the ad post form as well so it's got
and the ad post form as well so it's got a little bit of the ingredients of both
a little bit of the ingredients of both but really nothing new so we're
but really nothing new so we're importing in use state because we're
importing in use state because we're still going to use the u state hook for
still going to use the u state hook for the local state of the form then we've
the local state of the form then we've got use dispatch and use selector that
got use dispatch and use selector that we're bringing in from react redux we've
we're bringing in from react redux we've got our selectors select post by id
got our selectors select post by id and then we're going to bring in an
and then we're going to bring in an update post that we haven't created yet
update post that we haven't created yet but we will be doing that next with the
but we will be doing that next with the post slice because that is our update in
post slice because that is our update in our crud we've got create read now we're
our crud we've got create read now we're going to update and we can of course see
going to update and we can of course see the create and read already in the post
the create and read already in the post slice that were created in the previous
slice that were created in the previous tutorial okay use params but then i said
tutorial okay use params but then i said nothing new here is the one new hook
nothing new here is the one new hook that you haven't seen yet from react
that you haven't seen yet from react router it's use navigate we're also
router it's use navigate we're also bringing that in and then we're bringing
bringing that in and then we're bringing in select all users from our user slice
in select all users from our user slice not our post slice
not our post slice so now as we review
so now as we review we're getting the params because we need
we're getting the params because we need that post id just like we do with a
that post id just like we do with a single post page we're also creating
single post page we're also creating navigate so we can use it later
navigate so we can use it later then we're using the selector to select
then we're using the selector to select post by id and we're also using a
post by id and we're also using a selector to get all of the users
selector to get all of the users then we have our state and this state is
then we have our state and this state is much like you've seen before when we
much like you've seen before when we added a new post and we also have a
added a new post and we also have a request status ready to go as we would
request status ready to go as we would dispatch that update and of course we
dispatch that update and of course we are bringing in the use dispatch hook
are bringing in the use dispatch hook here so we put the dispatch here now
here so we put the dispatch here now this post with the return when the post
this post with the return when the post is not found has to be after all of the
is not found has to be after all of the hooks it cannot be before or you will
hooks it cannot be before or you will get an error from react and as i scroll
get an error from react and as i scroll down now we have the handlers for when
down now we have the handlers for when the form input changes title content and
the form input changes title content and author we have a can save variable and
author we have a can save variable and i'll press ctrl b so we can see all of
i'll press ctrl b so we can see all of that and this is just like we have in
that and this is just like we have in the add new post form as well so we're
the add new post form as well so we're making sure there is title content and
making sure there is title content and user id all of those must be true
user id all of those must be true and the request status must be idle
and the request status must be idle and then when we click to save the post
and then when we click to save the post and i'll press alt z so the code wraps
and i'll press alt z so the code wraps so you can see all of it this is a
so you can see all of it this is a little different now
little different now just because we have more information in
just because we have more information in the post when the post is first created
the post when the post is first created we're pulling in information from our
we're pulling in information from our fake api that jason placeholder api and
fake api that jason placeholder api and then when we do that and we add a new
then when we do that and we add a new post to our state we're adding in the
post to our state we're adding in the reactions and the date because they
reactions and the date because they didn't previously exist at the api so
didn't previously exist at the api so it's just something we had to do to
it's just something we had to do to adapt but now that we're updating the
adapt but now that we're updating the post we need to include all of the
post we need to include all of the information we have except for the date
information we have except for the date because we'll set a new date
because we'll set a new date and then we use unwrap which of course
and then we use unwrap which of course throws an error
throws an error and lets us go to the catch block if an
and lets us go to the catch block if an error happens
error happens and that is something we covered in the
and that is something we covered in the previous tutorial as well but it
previous tutorial as well but it essentially
essentially lets that promise either reject or
lets that promise either reject or create an error and then it represents
create an error and then it represents that here and allows us to use try catch
that here and allows us to use try catch logic here's the navigate we created
logic here's the navigate we created which is something new so after we edit
which is something new so after we edit this post we're going to go back to the
this post we're going to go back to the individual post page
individual post page and view the post that has the id now as
and view the post that has the id now as we scroll down and get to the jsx we
we scroll down and get to the jsx we also have to create user options to once
also have to create user options to once again populate that drop menu just like
again populate that drop menu just like when we create a new post and it will
when we create a new post and it will have all the users names in there so we
have all the users names in there so we could change the author if we want to
could change the author if we want to and then this form is very much like the
and then this form is very much like the add new post form one change here though
add new post form one change here though is we had to provide a default value for
is we had to provide a default value for the user id in the select and that is
the user id in the select and that is because the post already has an author
because the post already has an author so we want to show who was the author of
so we want to show who was the author of the post even if it's going to be
the post even if it's going to be changed other than that it's pretty much
changed other than that it's pretty much the same as the add new post form so
the same as the add new post form so that covers everything there's quite a
that covers everything there's quite a bit of code there though so if i went
bit of code there though so if i went too fast make sure you download that
too fast make sure you download that source code now at the top of the file
source code now at the top of the file we imported update post in from the post
we imported update post in from the post slice but we haven't created that yet so
slice but we haven't created that yet so let's jump back to the post slice and
let's jump back to the post slice and let's add that update crud operation so
let's add that update crud operation so we'll scroll up to where we've created
we'll scroll up to where we've created these other async thunks that are above
these other async thunks that are above the slice we've got fetch posts and add
the slice we've got fetch posts and add new posts already
new posts already so we'll see what variation there is as
so we'll see what variation there is as this is slightly different than add new
this is slightly different than add new post when we update a post i've pasted
post when we update a post i've pasted in the new async thunk for update post
in the new async thunk for update post and we can see its posts update post is
and we can see its posts update post is the label and then what we're sending in
the label and then what we're sending in once again control b so it doesn't
once again control b so it doesn't scroll off the screen we're sending in
scroll off the screen we're sending in that initial post data which is what
that initial post data which is what that is and we're
that is and we're destructuring and getting the id from
destructuring and getting the id from that initial post because we need the id
that initial post because we need the id in the url
in the url as we send this update to the api and
as we send this update to the api and we're now using the http method put with
we're now using the http method put with axios the rest of this is structured
axios the rest of this is structured very similar to what you saw before up
very similar to what you saw before up here and of course we're sending along
here and of course we're sending along that post data because we're now putting
that post data because we're now putting the data to update the existing post
the data to update the existing post that has whatever id that we pass into
that has whatever id that we pass into this url and as we previously learned in
this url and as we previously learned in the last lesson about async thunks
the last lesson about async thunks they're handled with extra reducers
they're handled with extra reducers where it receives a builder object and
where it receives a builder object and that builder responds to different cases
that builder responds to different cases so here we have the ad case for fetch
so here we have the ad case for fetch posts and it listens to pending
posts and it listens to pending fulfilled
fulfilled and rejected as far as the promise date
and rejected as far as the promise date and then the add new post listen to
and then the add new post listen to fulfilled and that's what we're going to
fulfilled and that's what we're going to do again with the update so just
do again with the update so just underneath the previous case for add new
underneath the previous case for add new post
post here we're going to paste in our new
here we're going to paste in our new case and of course when i save we'll get
case and of course when i save we'll get some better formatting here as well
some better formatting here as well so saving of course adjusted that for us
so saving of course adjusted that for us now let's look at this update post
now let's look at this update post because it's slightly different
because it's slightly different we're getting some information
we're getting some information back here with the action payload
back here with the action payload but we could have a successful
but we could have a successful post essentially a post that is not
post essentially a post that is not rejected as a promise but it might not
rejected as a promise but it might not have the status 200 it might not have
have the status 200 it might not have completed the update say the server
completed the update say the server sends a status code of 500 an error
sends a status code of 500 an error and we'll discuss why this could happen
and we'll discuss why this could happen especially with our fake api in a moment
especially with our fake api in a moment but let's first just consider the facts
but let's first just consider the facts so if the payload does not have the id
so if the payload does not have the id property and we're checking that with
property and we're checking that with optional chaining here the question mark
optional chaining here the question mark in the dot then we're just going to log
in the dot then we're just going to log that the update could not complete
that the update could not complete because what's really going to return is
because what's really going to return is the error message from the catch block
the error message from the catch block of axios so that action payload here but
of axios so that action payload here but it would still
it would still not be considered an error it would be
not be considered an error it would be considered fulfilled because axios still
considered fulfilled because axios still return that information so
return that information so what happens is we get our error message
what happens is we get our error message right here and then we just return to in
right here and then we just return to in this but if everything goes as planned
this but if everything goes as planned we can destructure the id from the
we can destructure the id from the action payload we can set a new date on
action payload we can set a new date on the action payload and then we can go
the action payload and then we can go ahead and filter out
ahead and filter out the previous post with the same id and
the previous post with the same id and then we can update our state with all
then we can update our state with all the previous posts and then of course
the previous posts and then of course pass in the new post so let's go back to
pass in the new post so let's go back to our edit post form and make sure we
our edit post form and make sure we applied everything from update post
applied everything from update post correctly we already had the import here
correctly we already had the import here now let's look and make sure we're
now let's look and make sure we're dispatching it correctly as well so when
dispatching it correctly as well so when we have the dispatch it's right here and
we have the dispatch it's right here and we're calling our async thunk update
we're calling our async thunk update post and we're passing in all of the
post and we're passing in all of the information that we need right here
information that we need right here again
again the only property that is not being
the only property that is not being passed in is the date because we create
passed in is the date because we create a new one with that confirmed let's go
a new one with that confirmed let's go back to our file tree and go back to our
back to our file tree and go back to our app.js so we can pull in our edit form
app.js so we can pull in our edit form and apply the proper routing as well so
and apply the proper routing as well so after our single post page
after our single post page we can say
we can say import
import edit post form and their visual studio
edit post form and their visual studio code helps us out it's from features
code helps us out it's from features posts and then our edit post form
posts and then our edit post form component and then this will once again
component and then this will once again be a child of our post route and so
be a child of our post route and so after we have our single post page here
after we have our single post page here we can paste this in and look at the
we can paste this in and look at the route for editing a post so now we would
route for editing a post so now we would go to post slash post slash edit
go to post slash post slash edit and then the post id and then we'll see
and then the post id and then we'll see our edit post form now let's drag visual
our edit post form now let's drag visual studio code to the left
studio code to the left and i'll go ahead and drag our blog so
and i'll go ahead and drag our blog so it fills up the entire screen it looks a
it fills up the entire screen it looks a little better this way we can go ahead
little better this way we can go ahead and add a few votes for coffee on the
and add a few votes for coffee on the first post and make sure they carry over
first post and make sure they carry over to the viewpost page and they do our
to the viewpost page and they do our state still stays updated and represents
state still stays updated and represents exactly what it should be
exactly what it should be now if we click edit post we see the
now if we click edit post we see the edit post form and here we've pulled in
edit post form and here we've pulled in the post title and content so we should
the post title and content so we should see if we could go ahead and update this
see if we could go ahead and update this let's select all of the title and just
let's select all of the title and just say
say shorter title right here and we'll leave
shorter title right here and we'll leave the author as leanne graham and now
the author as leanne graham and now inside the content area i'll select all
inside the content area i'll select all of that and just say
of that and just say hey there we'll go down to our post
hey there we'll go down to our post press enter
press enter and now we see the new post so we're at
and now we see the new post so we're at the post page not the edit post page has
the post page not the edit post page has a shorter title still has seven votes
a shorter title still has seven votes for coffee and the update async thunk
for coffee and the update async thunk worked as expected now let's go back to
worked as expected now let's go back to the home page and we see the full list
the home page and we see the full list of posts and once again we see our new
of posts and once again we see our new title and new content in the first post
title and new content in the first post and we're on the home page let's go back
and we're on the home page let's go back to vs code i'll drag the app to the
to vs code i'll drag the app to the right
right let vs code fill the screen
let vs code fill the screen and we need to go back to the post slice
and we need to go back to the post slice because now we want to go ahead and
because now we want to go ahead and create an async thunk that will allow us
create an async thunk that will allow us to delete a post as well so now in the
to delete a post as well so now in the post slice ctrl b to hide that file tree
post slice ctrl b to hide that file tree and instead of way down by the builders
and instead of way down by the builders let's go up where we've created our
let's go up where we've created our async thunks and right after update post
async thunks and right after update post i will press enter a couple of times to
i will press enter a couple of times to allow some room and paste in our delete
allow some room and paste in our delete post which is also very similar but
post which is also very similar but let's look at the differences so here
let's look at the differences so here we've labeled it post slash delete post
we've labeled it post slash delete post we're still receiving initial post data
we're still receiving initial post data we're still destructuring and getting
we're still destructuring and getting that id from that initial post data
that id from that initial post data and now we're going to go to axios
and now we're going to go to axios axios.delete so the http method delete
axios.delete so the http method delete and the url looks just like it did for
and the url looks just like it did for our update post it needs the id to know
our update post it needs the id to know which post to delete now we see some
which post to delete now we see some things here that are almost unique to
things here that are almost unique to our fake rest api that we're using from
our fake rest api that we're using from jsonplaceholder because
jsonplaceholder because even though we send the delete request
even though we send the delete request jsonplaceholder doesn't send back the id
jsonplaceholder doesn't send back the id typically a rest api would send back the
typically a rest api would send back the id of the post you just deleted at least
id of the post you just deleted at least in my experience but json placeholder
in my experience but json placeholder doesn't do that if anything we just get
doesn't do that if anything we just get an empty object so what we're doing here
an empty object so what we're doing here is checking to see if the response
is checking to see if the response status is 200 and if so
status is 200 and if so then we're just returning that same
then we're just returning that same initial post data so we can grab the id
initial post data so we can grab the id out of it inside of our builder case as
out of it inside of our builder case as we move down here in the post slice but
we move down here in the post slice but if it does not have a status of 200 then
if it does not have a status of 200 then we're returning a message that has
we're returning a message that has whatever status and status text there is
whatever status and status text there is so that could at least be logged if we
so that could at least be logged if we did not get the correct information that
did not get the correct information that we expected that says our post is
we expected that says our post is deleted and this is essentially passing
deleted and this is essentially passing that id along so now let's add our
that id along so now let's add our builder case to handle this delete post
builder case to handle this delete post async thunk so as we scroll down to the
async thunk so as we scroll down to the bottom of our add case list
bottom of our add case list i'll paste in this case
i'll paste in this case and save it looks like it's already
and save it looks like it's already formatted well so we're looking for
formatted well so we're looking for fulfilled again on the delete post and
fulfilled again on the delete post and here this is much like what we had in
here this is much like what we had in the create post so we're making sure we
the create post so we're making sure we have that id property here with optional
have that id property here with optional chaining we're checking for that on the
chaining we're checking for that on the payload and if it does not exist for any
payload and if it does not exist for any reason we're then saying the delete
reason we're then saying the delete could not be completed it says delete
could not be completed it says delete could not complete and we log whatever
could not complete and we log whatever the action payload is which could be
the action payload is which could be that error message it's whatever that
that error message it's whatever that status and status text would be
status and status text would be and then otherwise we're destructuring
and then otherwise we're destructuring getting the id
getting the id and then we're filtering out all of the
and then we're filtering out all of the other posts that are not equal to that
other posts that are not equal to that id and then we're just setting the state
id and then we're just setting the state to those posts because we've essentially
to those posts because we've essentially deleted that post and so we don't want
deleted that post and so we don't want it in the state any longer and now let's
it in the state any longer and now let's go to the edit post form and allow a
go to the edit post form and allow a post to be deleted as well essentially
post to be deleted as well essentially let's put that async thunk we just
let's put that async thunk we just created into action so besides the
created into action so besides the select post
select post by id and update post from the post
by id and update post from the post slice we also need to import delete post
slice we also need to import delete post and now when we scroll down we already
and now when we scroll down we already have our on save post clicked so this
have our on save post clicked so this one will be very similar
one will be very similar we'll just come down here after the
we'll just come down here after the users options and we'll put in on delete
users options and we'll put in on delete post clicked and we can see we still set
post clicked and we can see we still set the status to depending
the status to depending pending not depending
pending not depending and then we have
and then we have dispatch and we're dispatching our
dispatch and we're dispatching our delete post all we need to pass in is
delete post all we need to pass in is the id because that's all that's needed
the id because that's all that's needed to send to the api to delete the post
to send to the api to delete the post and of course that's all that's needed
and of course that's all that's needed to remove it from our state as well we
to remove it from our state as well we still use unwrap here so we can use try
still use unwrap here so we can use try catch logic we still use navigate but
catch logic we still use navigate but now after we delete a post we just want
now after we delete a post we just want to navigate back to the home page so we
to navigate back to the home page so we just navigate to the slash
just navigate to the slash and then as far as the rest of this goes
and then as far as the rest of this goes we just set the request status back to
we just set the request status back to idle as we do with the on save post
idle as we do with the on save post clicked and we just log the error the
clicked and we just log the error the same as we do with the on save post
same as we do with the on save post clicked as well but now to call the
clicked as well but now to call the delete into action we need to add a
delete into action we need to add a separate button for that so after our
separate button for that so after our save post button we'll just put the
save post button we'll just put the delete right here underneath
delete right here underneath paste that in and you can see it's just
paste that in and you can see it's just calling that on delete post clicked and
calling that on delete post clicked and we'll save a very small thing that i
we'll save a very small thing that i just noticed no big deal but this was
just noticed no big deal but this was using backticks so at some point it was
using backticks so at some point it was a template literal and i just changed it
a template literal and i just changed it it doesn't need to have backticks when
it doesn't need to have backticks when i'm not passing anything in so i'll just
i'm not passing anything in so i'll just use single quotes there instead of the
use single quotes there instead of the backticks and save in our navigate and
backticks and save in our navigate and while we're at it concerning this
while we're at it concerning this navigate let's go to our file tree go to
navigate let's go to our file tree go to the add post form and allow some
the add post form and allow some navigation as well after we add that new
navigation as well after we add that new post so we're going to import
post so we're going to import use navigate from react router dom
use navigate from react router dom and after we have that we need to apply
and after we have that we need to apply well we need to first define our
well we need to first define our navigate from use navigate so let's post
navigate from use navigate so let's post that paste that in as well here but
that paste that in as well here but i'll save keep that on a separate line
i'll save keep that on a separate line so now we can define navigate and use it
so now we can define navigate and use it after our post is saved and once again
after our post is saved and once again after we create a new post we just want
after we create a new post we just want to go back to the home page so here
to go back to the home page so here after we set all of the local state for
after we set all of the local state for the form we'll just navigate back to the
the form we'll just navigate back to the home page so now we can try more of this
home page so now we can try more of this out let's drag visual studio code to the
out let's drag visual studio code to the left drag the app to full screen and
left drag the app to full screen and test everything out we're here on the
test everything out we're here on the home page of course it reloaded and when
home page of course it reloaded and when it reloaded we lost our state there but
it reloaded we lost our state there but we've got say four thumbs up nine
we've got say four thumbs up nine coffees we can view the post it goes
coffees we can view the post it goes ahead and keeps those reactions we can
ahead and keeps those reactions we can edit the post again
edit the post again and we'll say
and we'll say small title and then
small title and then inside of here we'll just say hey and
inside of here we'll just say hey and now we have our new post essentially our
now we have our new post essentially our edited post that has a small title and
edited post that has a small title and says hey
says hey all of that looks good we go back to the
all of that looks good we go back to the home page
home page that's good too so now let's go to the
that's good too so now let's go to the post page let's add a new post and we
post page let's add a new post and we can say
can say hey there and give another author and
hey there and give another author and then we'll say
then we'll say small post number two
small post number two and then save and now we've got a second
and then save and now we've got a second post as well so we can create notice
post as well so we can create notice after we save that new post we navigated
after we save that new post we navigated right back to the home page
right back to the home page now let's delete a post so when we go to
now let's delete a post so when we go to view post then we can go to edit post
view post then we can go to edit post and if i scroll down yep we've got a
and if i scroll down yep we've got a delete post button now so this is
delete post button now so this is post from leanne graham that had small
post from leanne graham that had small title and hey if we delete the post we
title and hey if we delete the post we have navigated back to the home page and
have navigated back to the home page and you can see
you can see her post was not this one
her post was not this one it said a small title i believe so it is
it said a small title i believe so it is gone but we still have our hey there
gone but we still have our hey there post
post now here's something about new posts and
now here's something about new posts and working with the fake api we really
working with the fake api we really can't update them because it doesn't
can't update them because it doesn't exist
exist on the fake api so this would be like
on the fake api so this would be like post 101 instead of the 100 posts from
post 101 instead of the 100 posts from that api so if we go to the edit and we
that api so if we go to the edit and we want to say small post number 23
want to say small post number 23 and
and then put you after this
then put you after this and then we save
and then we save it doesn't go ahead and update notice we
it doesn't go ahead and update notice we don't have those changes and that's
don't have those changes and that's because we got that message back from
because we got that message back from the api where it really wasn't a
the api where it really wasn't a successful update so let's quickly look
successful update so let's quickly look at that and i'll show you a change you
at that and i'll show you a change you can make to make sure that your state is
can make to make sure that your state is working fine as you want it to and
working fine as you want it to and ignore that response from the api but
ignore that response from the api but you wouldn't want to leave it this way
you wouldn't want to leave it this way normally so let's look at the post slice
normally so let's look at the post slice and we'll go to the update async thunk
and we'll go to the update async thunk that we created there is our update post
that we created there is our update post and instead of returning the error
and instead of returning the error message here which is what is happening
message here which is what is happening and then we're just exiting out of our
and then we're just exiting out of our builder case what happens is we could
builder case what happens is we could return the
return the initial post that once again has that
initial post that once again has that same data that we were updating with and
same data that we were updating with and that's what we expect the api to send
that's what we expect the api to send back when it is successful of course it
back when it is successful of course it sends a 500 a server
sends a 500 a server status 500 because it cannot update a
status 500 because it cannot update a post that doesn't exist at the api we
post that doesn't exist at the api we can interact with this fake api but we
can interact with this fake api but we can't really create the post there so if
can't really create the post there so if we save this change and i guess we
we save this change and i guess we should note
should note only for
only for testing redux
and save so if we change this then we should go ahead and get our state
should go ahead and get our state updated correctly i'll move this back to
updated correctly i'll move this back to the left and yeah we've got post not
the left and yeah we've got post not found because we made some updates and
found because we made some updates and changes now so let's go back to home
changes now so let's go back to home let's create a new post so this would be
let's create a new post so this would be post id 101 we'll say hey
post id 101 we'll say hey and pretty much say the same thing here
and pretty much say the same thing here save post there's our new post now we
save post there's our new post now we can view it
can view it and after we view it let's go to edit
and after we view it let's go to edit post
post and save post hey there let's see if we
and save post hey there let's see if we can go ahead and update this with you
can go ahead and update this with you and save and now we've got hey there you
and save and now we've got hey there you so it did update as we wanted it to it
so it did update as we wanted it to it does look like like just like the end of
does look like like just like the end of the last lesson there's somewhere that i
the last lesson there's somewhere that i have named the emojis incorrectly
have named the emojis incorrectly because we're not getting numbers next
because we're not getting numbers next to all of those let's see if we can find
to all of those let's see if we can find that by pulling this back to the right
that by pulling this back to the right and looking at visual studio code and in
and looking at visual studio code and in the post slice i bet we have somewhere
the post slice i bet we have somewhere named those incorrectly because it
named those incorrectly because it should be
should be start with a thumbs up and end with a
start with a thumbs up and end with a coffee every time let's make sure we're
coffee every time let's make sure we're getting those accurate and here is the
getting those accurate and here is the problem our add new post fulfilled was
problem our add new post fulfilled was not updated at least in this code
not updated at least in this code so i'll save that and that could have
so i'll save that and that could have actually been in the source code from
actually been in the source code from the starter code as well so you want to
the starter code as well so you want to make sure you have all of those named
make sure you have all of those named accurately and then
accurately and then the names and or at least the emojis and
the names and or at least the emojis and the numbers should show up correctly
the numbers should show up correctly i'll drag this back to the left once
i'll drag this back to the left once again not found but let's create a new
again not found but let's create a new post and make sure that
post and make sure that goes ahead and updates as we wanted to
goes ahead and updates as we wanted to hey
hey there and yes we've got everything
there and yes we've got everything accurate there save
accurate there save let's say again
let's say again and updated yes we still have all the
and updated yes we still have all the numbers by the emojis so that looks good
numbers by the emojis so that looks good as well now it's currently worth noting
as well now it's currently worth noting that if we go to the view post page and
that if we go to the view post page and then we refresh even though we're
then we refresh even though we're loading in data from the api we get post
loading in data from the api we get post not found but we can go ahead and
not found but we can go ahead and correct this behavior so let's pull this
correct this behavior so let's pull this to the right
to the right and go back to visual studio code and
and go back to visual studio code and for visual studio code we're going to go
for visual studio code we're going to go to the index js
to the index js and if you remember from a previous
and if you remember from a previous tutorial
tutorial we are loading the users immediately at
we are loading the users immediately at the app load well really that's all we
the app load well really that's all we need to do as far as getting the posts
need to do as far as getting the posts from the api as well so let's go ahead
from the api as well so let's go ahead and import
and import our fetch posts from the post slice as
our fetch posts from the post slice as well
well and then we can dispatch
and then we can dispatch that fetch posts as just like we are
that fetch posts as just like we are fetch users so we'll have posts there
fetch users so we'll have posts there and now we just need to make some
and now we just need to make some changes in our post list so in the file
changes in our post list so in the file tree i'll scroll to post lists and here
tree i'll scroll to post lists and here at the top
at the top now we're not going to need some of the
now we're not going to need some of the things that we were using
things that we were using one of those things is use effect so we
one of those things is use effect so we can remove that
can remove that another is the import of fetch posts
another is the import of fetch posts because we'll no longer be using it here
because we'll no longer be using it here and finally use dispatch because we will
and finally use dispatch because we will no longer be dispatching fetch posts as
no longer be dispatching fetch posts as well so i could remove this empty line
well so i could remove this empty line here and now inside of our code we can
here and now inside of our code we can remove the definition of dispatch
remove the definition of dispatch and we can remove use effect where fetch
and we can remove use effect where fetch post is called and after i do that i'll
post is called and after i do that i'll go ahead and save okay once again
go ahead and save okay once again dragging visual studio code to the left
dragging visual studio code to the left and expanding the blog that we have and
and expanding the blog that we have and now when we load the page just like when
now when we load the page just like when i hit reload we instantly have the posts
i hit reload we instantly have the posts now when i go to view post and i hit
now when i go to view post and i hit reload
reload we still have the post so again feel
we still have the post so again feel free to download the css that i have
free to download the css that i have from the source code and tweak it and
from the source code and tweak it and maybe fix a little thing or two that i
maybe fix a little thing or two that i have overlooked possibly otherwise
have overlooked possibly otherwise everything is very complete and we have
everything is very complete and we have all crud operations now inside of the
all crud operations now inside of the post slice for our different blog posts
post slice for our different blog posts so if we scroll up and look at our async
so if we scroll up and look at our async thunks we have fetch posts add new post
thunks we have fetch posts add new post update post and delete post
update post and delete post i've got our react redux blog project
i've got our react redux blog project open here on the left and on the right
open here on the left and on the right i've got dev tools open and it's the
i've got dev tools open and it's the react dev tools i use the profiler to
react dev tools i use the profiler to record our application every time i
record our application every time i clicked the thumbs up emoji for the
clicked the thumbs up emoji for the first post and as you can see from the
first post and as you can see from the three screens that i have every time i
three screens that i have every time i clicked that emoji i re-rendered all 100
clicked that emoji i re-rendered all 100 posts even though the emoji is just for
posts even though the emoji is just for the first post today we'll fix that and
the first post today we'll fix that and apply some other optimizations to our
apply some other optimizations to our application okay i've got visual studio
application okay i've got visual studio code open here and we're at the edit
code open here and we're at the edit post form of the starter code now you
post form of the starter code now you can download this starter code from the
can download this starter code from the link in the description below or if
link in the description below or if you've been working through this series
you've been working through this series with me maybe you've already got it and
with me maybe you've already got it and that's what i want to address before we
that's what i want to address before we get started with anything else one thing
get started with anything else one thing from the previous tutorial in this
from the previous tutorial in this series in the edit post form dot js
series in the edit post form dot js and that is on the on author changed i
and that is on the on author changed i don't believe in the previous tutorial i
don't believe in the previous tutorial i wrapped this value in number and it
wrapped this value in number and it needs to be a number otherwise it saves
needs to be a number otherwise it saves a string and then the comparison doesn't
a string and then the comparison doesn't work and you don't get the updated
work and you don't get the updated author now again this was already
author now again this was already changed in the repository for the
changed in the repository for the starting code so if you've just
starting code so if you've just downloaded that you've already got this
downloaded that you've already got this here now before i apply optimizations
here now before i apply optimizations today i want to add a couple of quick
today i want to add a couple of quick features that will help me demonstrate
features that will help me demonstrate these optimizations the first one is
these optimizations the first one is going to be in the users folder and
going to be in the users folder and we're going to create a users list so
we're going to create a users list so i'll start a new file and name this
i'll start a new file and name this users with a capital u and then list
users with a capital u and then list with a capital l dot js nothing really
with a capital l dot js nothing really new in the file so i'll just paste in
new in the file so i'll just paste in the ingredients and we'll quickly cover
the ingredients and we'll quickly cover this now i'll get rid of that extra line
this now i'll get rid of that extra line at the top but we're importing use
at the top but we're importing use selector as we have before and our
selector as we have before and our select all users selector and then link
select all users selector and then link from react router dom and then inside
from react router dom and then inside the component
the component we are getting the users by calling the
we are getting the users by calling the use selector here and passing in the
use selector here and passing in the select all users selector that we
select all users selector that we created in the user slice
created in the user slice and then we render the users so inside
and then we render the users so inside of render users is an array full of
of render users is an array full of these list items because we're calling
these list items because we're calling map over all of the users and then each
map over all of the users and then each user gets their own link
user gets their own link and then of course it links to an
and then of course it links to an individual page for each user based on
individual page for each user based on that user id and then you can see we
that user id and then you can see we just returned the rendered users here at
just returned the rendered users here at the end of the component and so that's
the end of the component and so that's essentially the entire users list
essentially the entire users list component now we need to create the user
component now we need to create the user page for each user
page for each user but before we do that we need to go to
but before we do that we need to go to the user slice and create a select user
the user slice and create a select user by id selector so let's scroll down
by id selector so let's scroll down and once we get down to the bottom here
and once we get down to the bottom here just under select all users we'll add
just under select all users we'll add some space
some space i'll paste this in just to go a little
i'll paste this in just to go a little faster but it's really easy to create we
faster but it's really easy to create we call it select user by id gets the state
call it select user by id gets the state and the user id
and the user id and then we just call the user state
and then we just call the user state here state dot users and then find on
here state dot users and then find on that
that and we return
and we return what matches the user dot id to the user
what matches the user dot id to the user id that we pass in and of course we have
id that we pass in and of course we have export here so it's ready to go and
export here so it's ready to go and we'll be able to import it into the user
we'll be able to import it into the user page that we create so now let's create
page that we create so now let's create this new component and we'll call it
this new component and we'll call it user not users but just user singular
user not users but just user singular page with a capital p dot js this
page with a capital p dot js this component doesn't have much new either
component doesn't have much new either so i'll paste this in now of course it's
so i'll paste this in now of course it's going to be able to display any given
going to be able to display any given user that has their data passed in so at
user that has their data passed in so at the top we have use selector and then
the top we have use selector and then we're importing that select user by id
we're importing that select user by id that we just created in the user slice
that we just created in the user slice we're also importing select all posts
we're also importing select all posts and then from react router we're
and then from react router we're importing link and the use params hook
importing link and the use params hook so we're going to get that user id out
so we're going to get that user id out of the url and that's what we're doing
of the url and that's what we're doing right here is we call use params we're
right here is we call use params we're grabbing that user id now note that will
grabbing that user id now note that will be a string as it comes from the url so
be a string as it comes from the url so we need to wrap it in number once again
we need to wrap it in number once again when we pass it into a selector and
when we pass it into a selector and that's what we're doing here to get the
that's what we're doing here to get the user we're calling use selector and of
user we're calling use selector and of course inside that it receives the state
course inside that it receives the state and then we use that selector we created
and then we use that selector we created select user by id which receives the
select user by id which receives the state and the user id that must be
state and the user id that must be wrapped as a number
wrapped as a number and then we have posts for user because
and then we have posts for user because what we want to do is not only get the
what we want to do is not only get the user we want to display a list of all of
user we want to display a list of all of their posts so once again we use use
their posts so once again we use use selector we pass in the state
selector we pass in the state and then we use select all posts
and then we use select all posts inside of the use selector to define all
inside of the use selector to define all posts
posts and then we call filter on all posts and
and then we call filter on all posts and return the result where the post dot
return the result where the post dot user id matches the user id so we get
user id matches the user id so we get all of the posts that belong to any
all of the posts that belong to any given user and then we list those out
given user and then we list those out and now we link the titles of those
and now we link the titles of those posts to a specific post id page which
posts to a specific post id page which we've already created in a previous
we've already created in a previous tutorial so we can go to a specific post
tutorial so we can go to a specific post for any given post they have their own
for any given post they have their own page already and then of course down
page already and then of course down here we're just displaying the name in
here we're just displaying the name in an h2 and all of those post titles with
an h2 and all of those post titles with their links and that is the end of the
their links and that is the end of the user page component all right with those
user page component all right with those components created and the selector
components created and the selector created in the user slice we're ready to
created in the user slice we're ready to go to app js now just under the import
go to app js now just under the import of the edit post form we're going to
of the edit post form we're going to import user list and we're going to
import user list and we're going to import user page after that we need to
import user page after that we need to scroll down and this will look a lot
scroll down and this will look a lot like the path to the post information
like the path to the post information here where we have route path equals
here where we have route path equals post but this will be for user and i'll
post but this will be for user and i'll paste this in i'll save to get some
paste this in i'll save to get some better formatting and we can see we've
better formatting and we can see we've got our path user then there's an index
got our path user then there's an index route and it's going to display the user
route and it's going to display the user list component and then if the route has
list component and then if the route has an id a user id at the end of it
an id a user id at the end of it then it's going to display the user page
then it's going to display the user page component and while we're in the app.js
component and while we're in the app.js let's scroll up i need to import
let's scroll up i need to import navigate from react router dom
navigate from react router dom and we're going to add a catch-all page
and we're going to add a catch-all page now you could create a 404
now you could create a 404 and display it but what i'm going to do
and display it but what i'm going to do is just put essentially a redirect here
is just put essentially a redirect here with navigate and we'll navigate back to
with navigate and we'll navigate back to the home page if any page doesn't exist
the home page if any page doesn't exist but as i note here in a comment you
but as i note here in a comment you could replace with a 404 if you want to
could replace with a 404 if you want to and this is a catch-all it's got the
and this is a catch-all it's got the asterisk here which is going to select
asterisk here which is going to select any route that makes it past these other
any route that makes it past these other routes so if it doesn't match any of
routes so if it doesn't match any of these
these then it will be grabbed here and then
then it will be grabbed here and then it's just going to redirect to the home
it's just going to redirect to the home page with navigate notice i've got the
page with navigate notice i've got the replace flag here also and that's going
replace flag here also and that's going to replace the bad request whatever that
to replace the bad request whatever that address or page was that didn't exist
address or page was that didn't exist it's going to replace that in history
it's going to replace that in history with the good address that we're sending
with the good address that we're sending the user to now we're almost finished
the user to now we're almost finished with this and ready to test it out but
with this and ready to test it out but first let's go to the components
first let's go to the components directory go to the header and here
directory go to the header and here after the post link i'm going to press
after the post link i'm going to press shift alt and the down arrow to copy
shift alt and the down arrow to copy that line down and then we'll just
that line down and then we'll just change this to user but then here
change this to user but then here instead of post i'm going to say users
instead of post i'm going to say users because it's actually going to display a
because it's actually going to display a user's list so i'll save that change as
user's list so i'll save that change as well and now we're ready to test it out
well and now we're ready to test it out so i'm going to press control in the
so i'm going to press control in the backtick type npm start to start up our
backtick type npm start to start up our app and then drag visual studio code to
app and then drag visual studio code to the left
the left click on chrome so we can see what comes
click on chrome so we can see what comes up and we'll see if we have any errors
up and we'll see if we have any errors or if everything is working as expected
or if everything is working as expected and here's our blog it appears
and here's our blog it appears everything is working as expected we see
everything is working as expected we see users up here in the top right so i will
users up here in the top right so i will click on that and now we have our users
click on that and now we have our users page and we have our list of users so
page and we have our list of users so i'll just click on the first user and
i'll just click on the first user and now we have leanne graham from the data
now we have leanne graham from the data that we're getting from jsonplaceholder
that we're getting from jsonplaceholder which is the data source for this blog
which is the data source for this blog that we're making an example of and then
that we're making an example of and then we have tin post and of course this is
we have tin post and of course this is lorem epsom text here but these
lorem epsom text here but these different 10 titles of posts and we can
different 10 titles of posts and we can click one and go to any specific post as
click one and go to any specific post as well so it all worked out like we
well so it all worked out like we expected it to let's click and go back
expected it to let's click and go back to users and everything looks pretty
to users and everything looks pretty good here now we need to add one more
good here now we need to add one more feature before we can apply these
feature before we can apply these optimizations that i would like to so
optimizations that i would like to so i'm going to grab chrome drag it to the
i'm going to grab chrome drag it to the right grab visual studio code let it
right grab visual studio code let it fill out the page close the terminal and
fill out the page close the terminal and head over to the posts slice
head over to the posts slice and inside the post slice we're going to
and inside the post slice we're going to add a simple counter now it really has
add a simple counter now it really has no purpose in the blog but it's going to
no purpose in the blog but it's going to be a nice review for implementing some
be a nice review for implementing some new state with redux and it's also going
new state with redux and it's also going to help me demonstrate some
to help me demonstrate some optimizations so to do that we're going
optimizations so to do that we're going to start out here in our initial state
to start out here in our initial state and i'll put a comma and then i'll just
and i'll put a comma and then i'll just put a count value of 0 to go along with
put a count value of 0 to go along with the rest of the initial state next we're
the rest of the initial state next we're going to scroll down past all of our
going to scroll down past all of our async thunks and get down to the create
async thunks and get down to the create slice where we have our reducers now
slice where we have our reducers now we're not using post added anymore ever
we're not using post added anymore ever since we applied our async thunks so i
since we applied our async thunks so i can really eliminate that and if we come
can really eliminate that and if we come down here although i'll just select it
down here although i'll just select it all and hit backspace so we still have
all and hit backspace so we still have our reaction added now underneath
our reaction added now underneath reaction added i'm going to go ahead and
reaction added i'm going to go ahead and put in the other reducer that we have
put in the other reducer that we have here
here and that is going to be increased count
and that is going to be increased count it's very basic it accepts state and
it's very basic it accepts state and action just like reaction added does but
action just like reaction added does but then we're just taking state count and
then we're just taking state count and we're adding one to it now again you can
we're adding one to it now again you can write code that looks like it mutates
write code that looks like it mutates the data inside of create slice we can
the data inside of create slice we can only do this inside of create slice and
only do this inside of create slice and so that's what we're doing here just
so that's what we're doing here just kind of like you see here with the
kind of like you see here with the reactions as well so you might see code
reactions as well so you might see code that looks like it would mutate the data
that looks like it would mutate the data but immer js is running underneath the
but immer js is running underneath the hood only inside of the create slice and
hood only inside of the create slice and that's why we can do it here and now we
that's why we can do it here and now we need to create another selector for our
need to create another selector for our account so we'll scroll all the way down
account so we'll scroll all the way down here to our selectors i'll click on the
here to our selectors i'll click on the last one in that grouping where get post
last one in that grouping where get post error is and we'll just change this then
error is and we'll just change this then to get
to get count and then it's going to be state
count and then it's going to be state dot posts
dot posts dot count
dot count now action creator functions are
now action creator functions are automatically created when we put a
automatically created when we put a reducer in the create slice portion of
reducer in the create slice portion of the slice so we remove that post added
the slice so we remove that post added and so now we can add what we created
and so now we can add what we created which is called
which is called increase
increase count so we need to export that action
count so we need to export that action creator function now we can save our
creator function now we can save our changes here in the slice and what we're
changes here in the slice and what we're going to do is go to the header
going to do is go to the header component where we were just a little
component where we were just a little bit ago to add this user's link and
bit ago to add this user's link and we're going to apply the counter to this
we're going to apply the counter to this component so underneath our import of
component so underneath our import of link i'm just pasting in the other
link i'm just pasting in the other imports but we have use dispatch and use
imports but we have use dispatch and use selector from react redux and then we
selector from react redux and then we have increase count and git count from
have increase count and git count from the post slice so then we need to define
the post slice so then we need to define our dispatch here so we'll say const
our dispatch here so we'll say const dispatch equals use
dispatch equals use dispatch
dispatch and after that we also need to get our
and after that we also need to get our count so there we're going to use the
count so there we're going to use the selector we imported
selector we imported and we'll use git count that we created
and we'll use git count that we created and finally in the nav after the
and finally in the nav after the unordered list i'm just going to paste
unordered list i'm just going to paste in a button when i save it formats
in a button when i save it formats better but this button has an on click
better but this button has an on click and that's where we dispatch the
and that's where we dispatch the increase count function
increase count function and then
and then we have the count state on the button so
we have the count state on the button so that's all there is to it really let's
that's all there is to it really let's drag visual studio code back to the left
drag visual studio code back to the left and let's see what error we have it says
and let's see what error we have it says git count is not found inside of the
git count is not found inside of the post slice so let's see what's going on
post slice so let's see what's going on with that i'll need the full screen to
with that i'll need the full screen to figure that out let's look at the post
figure that out let's look at the post slice
slice and let's see if we have git count oh i
and let's see if we have git count oh i spelled it wrong i had an r at the end
spelled it wrong i had an r at the end once i remove that r and save we should
once i remove that r and save we should be good to go okay let's drag this back
be good to go okay let's drag this back to the left
to the left it looks like it's working now
it looks like it's working now and now everything seems to be working
and now everything seems to be working here's our button in the very top right
here's our button in the very top right and if i click it we should see it
and if i click it we should see it increment yep went right up to five
increment yep went right up to five after five clicks and now we're ready to
after five clicks and now we're ready to make our first optimization
make our first optimization and what you need here at least to
and what you need here at least to record and see that you need to make
record and see that you need to make optimizations is react dev tools now i'm
optimizations is react dev tools now i'm going to open up dev tools by right
going to open up dev tools by right clicking and choosing inspect you could
clicking and choosing inspect you could also press control shift and the letter
also press control shift and the letter i but once you're in dev tools then you
i but once you're in dev tools then you want to select the couple of greater
want to select the couple of greater than signs here that allow you to see
than signs here that allow you to see more tabs essentially
more tabs essentially and once you have react dev tools which
and once you have react dev tools which i'll link to in the description so if
i'll link to in the description so if you don't have those you can get it for
you don't have those you can get it for free at the chrome web store and it's an
free at the chrome web store and it's an extension you install for chrome
extension you install for chrome and i believe it's available for other
and i believe it's available for other browsers as well we're going to choose
browsers as well we're going to choose the profiler here and once we have the
the profiler here and once we have the profiler it wants us to start a
profiler it wants us to start a recording well i'm going to go to the
recording well i'm going to go to the page for leanne graham over here on the
page for leanne graham over here on the left so now we're at an individual user
left so now we're at an individual user page
page and then i'm going to start recording
and then i'm going to start recording our app and i'm going to go ahead and
our app and i'm going to go ahead and click the button five more times
click the button five more times after i've done that i'm going to stop
after i've done that i'm going to stop recording and now we can see the
recording and now we can see the components here and we have five pages
components here and we have five pages to arrow through
to arrow through and we're seeing what rendered so we can
and we're seeing what rendered so we can see this orange indicates the header
see this orange indicates the header rendered and that's correct because the
rendered and that's correct because the state changed but notice what else
state changed but notice what else happened the user page also rendered and
happened the user page also rendered and that's kind of strange because the user
that's kind of strange because the user page isn't related to the account at all
page isn't related to the account at all the counts in the header and that state
the counts in the header and that state really has nothing to do
really has nothing to do with the user page other than they're
with the user page other than they're both kept in the post slice
both kept in the post slice so if we arrow through our pages here
so if we arrow through our pages here we'll see that the user page is
we'll see that the user page is rendering every time that the header was
rendering every time that the header was updated and we still see that and so
updated and we still see that and so that's kind of
that's kind of strange and really not what we want so
strange and really not what we want so why is that happening let's go back and
why is that happening let's go back and take a look at our code once again i'll
take a look at our code once again i'll drag this over so it takes up the full
drag this over so it takes up the full page but we need to look at the code of
page but we need to look at the code of the user page component so here inside
the user page component so here inside of the user page component i'm going to
of the user page component i'm going to scroll up until we see the posts for
scroll up until we see the posts for user definition and here we're using the
user definition and here we're using the use selector we pass in the state
use selector we pass in the state then we select all posts with the select
then we select all posts with the select all post selector
all post selector and then we're returning all posts but
and then we're returning all posts but it's filtered
it's filtered and this is where we run into a problem
and this is where we run into a problem there's really nothing wrong with filter
there's really nothing wrong with filter it just returns a new array every time
it just returns a new array every time and use selector will run every time an
and use selector will run every time an action is dispatched and so when we
action is dispatched and so when we dispatch that increase count in the
dispatch that increase count in the header
header then the use selector runs again and it
then the use selector runs again and it forces a component to re-render if a new
forces a component to re-render if a new reference value is returned we're
reference value is returned we're returning a new value every time with
returning a new value every time with filter so that's why we're rendering the
filter so that's why we're rendering the user page and we can fix all of this by
user page and we can fix all of this by creating a memoized selector so let's go
creating a memoized selector so let's go back to the post slice and learn how to
back to the post slice and learn how to do this so back here in the post slice
do this so back here in the post slice i'll find it in the list over here on
i'll find it in the list over here on the left i want to scroll to the top
the left i want to scroll to the top first
first and let's look at our imports here we
and let's look at our imports here we have create slice nano id that we're no
have create slice nano id that we're no longer using so we can remove that we
longer using so we can remove that we have create async thunk and after that
have create async thunk and after that i'm going to import create
i'm going to import create selector and we'll use that to create
selector and we'll use that to create this memoize selector
this memoize selector so let's scroll down now to our
so let's scroll down now to our selectors all the way towards the bottom
selectors all the way towards the bottom and we'll find here we have select post
and we'll find here we have select post by id this is going to be just a little
by id this is going to be just a little bit different this is going to be select
bit different this is going to be select post
post by user so when i save i think i'll get
by user so when i save i think i'll get the formatting i want yes so here we
the formatting i want yes so here we have select posts by user and we're
have select posts by user and we're using our create selector create
using our create selector create selector accepts one or more input
selector accepts one or more input functions and notice they're inside of
functions and notice they're inside of brackets like an array that should be
brackets like an array that should be your first clue that these are
your first clue that these are dependencies actually the values
dependencies actually the values returned from these functions are the
returned from these functions are the dependencies and they provide
dependencies and they provide the input parameters for the output
the input parameters for the output function of our memoize selector so if
function of our memoize selector so if the select all post value changes or
the select all post value changes or this anonymous function which is taking
this anonymous function which is taking state and user id and it's simply
state and user id and it's simply returning the user id we just need the
returning the user id we just need the user id so we have to write a simple
user id so we have to write a simple function to do that because these are
function to do that because these are input functions
input functions but then if posts or the user id changes
but then if posts or the user id changes essentially that's the only time that
essentially that's the only time that we'll get something new
we'll get something new from this selector that's the only time
from this selector that's the only time that it will rerun so it's memoized so
that it will rerun so it's memoized so with this added now to our slice let's
with this added now to our slice let's go back to our user page and use this
go back to our user page and use this memoize selector so let's find the user
memoize selector so let's find the user page there it is now at the top we've
page there it is now at the top we've already got select user by id this is
already got select user by id this is going to be coming from the post slice
going to be coming from the post slice as well and this is select post by user
as well and this is select post by user so i'll just put it after
so i'll just put it after our select all posts and now that we've
our select all posts and now that we've imported it let's use it inside of the
imported it let's use it inside of the file so we'll come down here
file so we'll come down here where we were previously calling filter
where we were previously calling filter and creating that new value and we'll
and creating that new value and we'll just replace
just replace everything that we had for the post for
everything that we had for the post for user
user and now we'll use our new selector that
and now we'll use our new selector that we've created i'm going to press ctrl b
we've created i'm going to press ctrl b so we can see everything but here we're
so we can see everything but here we're using use selector once again passing in
using use selector once again passing in the state but now we're using this new
the state but now we're using this new memoized selector we created select
memoized selector we created select posts by user id it gets the state once
posts by user id it gets the state once again we're making sure it's a number
again we're making sure it's a number because we're getting that from use
because we're getting that from use params where it's a string from the url
params where it's a string from the url and then we're passing that user id in
and then we're passing that user id in so now that we've made these changes
so now that we've made these changes let's go ahead and drag visual studio
let's go ahead and drag visual studio code to the left let's go back let's
code to the left let's go back let's clear out the changes here and let's see
clear out the changes here and let's see if we need to reload or make any other
if we need to reload or make any other changes if we're getting everything we
changes if we're getting everything we expect we are not getting our posts
expect we are not getting our posts currently let's go back and quickly
currently let's go back and quickly check our code there may be something
check our code there may be something wrong with that selector we created so
wrong with that selector we created so i'll double check that that's back in
i'll double check that that's back in the post slice
the post slice as i'm looking through this
as i'm looking through this yes yes there is a problem we've got
yes yes there is a problem we've got post dot user i should have put post dot
post dot user i should have put post dot user id
user id and that's what we need to check so once
and that's what we need to check so once i make that change
i make that change we go back and now we'll of course make
we go back and now we'll of course make the
the chrome browser fill up the page and yes
chrome browser fill up the page and yes now we've got all the posts here on the
now we've got all the posts here on the individual user page so we're once again
individual user page so we're once again ready to check so what i'm going to do
ready to check so what i'm going to do is start recording again with react dev
is start recording again with react dev tools
clicking the number button five times and stopping
and stopping notice what happened now as we look on
notice what happened now as we look on our first page even we can see that
our first page even we can see that we've got it right we're rendering the
we've got it right we're rendering the header we're not rendering the user page
header we're not rendering the user page anymore so on each of these
anymore so on each of these attempts
attempts we did not re-render the user page and
we did not re-render the user page and that's why i wanted to add a counter
that's why i wanted to add a counter just to give something that was
just to give something that was completely
completely not a reference to what we had in the
not a reference to what we had in the other component and really out of the
other component and really out of the way as well to just show how one can
way as well to just show how one can impact the other if you do not apply the
impact the other if you do not apply the optimization correctly so now that we
optimization correctly so now that we have this memoized selector we're not
have this memoized selector we're not re-rendering the user page every time we
re-rendering the user page every time we increase the count okay with this
increase the count okay with this problem solved i'm going to clear out
problem solved i'm going to clear out the profiler again let's go back to the
the profiler again let's go back to the home page and while we're here i'll
home page and while we're here i'll start recording a profile again i'm just
start recording a profile again i'm just going to click thumbs up about three
going to click thumbs up about three times again
times again and stop the profile and let's see what
and stop the profile and let's see what we're getting so every time i clicked
we're getting so every time i clicked the thumbs up
the thumbs up we got not only the post list
we got not only the post list but every individual post excerpt was
but every individual post excerpt was also rendered so we've got 100 of those
also rendered so we've got 100 of those so one thumbs up meant re-rendering all
so one thumbs up meant re-rendering all of these and as i arrow through you'll
of these and as i arrow through you'll see they re-rendered every time we added
see they re-rendered every time we added a reaction so we do need to fix that as
a reaction so we do need to fix that as well and there's a couple of ways to do
well and there's a couple of ways to do it i'm going to drag chrome back over to
it i'm going to drag chrome back over to the right and dev tools will fill up the
the right and dev tools will fill up the screen i'm not dev tools vs code will
screen i'm not dev tools vs code will fill up the screen again and now there
fill up the screen again and now there is one quick way to do this that is
is one quick way to do this that is definitely legitimate and there's
definitely legitimate and there's nothing wrong with doing it this way
nothing wrong with doing it this way however we're going to look at a full
however we're going to look at a full featured solution after this also so
featured solution after this also so what we're going to do first is just say
what we're going to do first is just say import
import react
react from react we don't usually have to do
from react we don't usually have to do that but in this case we will
that but in this case we will we're going to change this const for
we're going to change this const for post excerpt to a let
post excerpt to a let and you'll quickly see why here because
and you'll quickly see why here because after that we're going to
after that we're going to set post as a post or post it's post
set post as a post or post it's post with a plural s at the end excerpt
with a plural s at the end excerpt and we'll set that equal to
and we'll set that equal to react dot memo
react dot memo and then we'll pass in posts
and then we'll pass in posts excerpt
excerpt and what that does really
and what that does really is it allows this component to not
is it allows this component to not re-render
re-render if
if the prop that it receives has not
the prop that it receives has not changed so if the post does not change
changed so if the post does not change that's passed to post excerpt
that's passed to post excerpt it will not re-render so this easily
it will not re-render so this easily solves the immediate problem that we
solves the immediate problem that we have so i'll just save that one change
have so i'll just save that one change right there and now i'll drag this back
right there and now i'll drag this back over
over we'll go ahead and look at chrome in the
we'll go ahead and look at chrome in the full screen again i'll clear out our
full screen again i'll clear out our previous recording
previous recording and we'll go back home and we'll start a
and we'll go back home and we'll start a recording
recording and i'll click
and i'll click three more thumbs up and now we'll stop
three more thumbs up and now we'll stop the recording
the recording and now look at our profile recording
and now look at our profile recording we've got the post list which is fine
we've got the post list which is fine and that's expected but we're only
and that's expected but we're only rendering this first post excerpt and of
rendering this first post excerpt and of course anything that's nested in it
course anything that's nested in it here's the time ago component which
here's the time ago component which that's so small it doesn't really hurt a
that's so small it doesn't really hurt a thing anyway but overall for this
thing anyway but overall for this example
example we just wanted that one post excerpt to
we just wanted that one post excerpt to render and that's what happened let's
render and that's what happened let's look at the next page same result and
look at the next page same result and the next page same result so now we
the next page same result so now we eliminated that big list okay there's
eliminated that big list okay there's nothing wrong with our react.memo
nothing wrong with our react.memo solution
solution but i'm going to remove all of this and
but i'm going to remove all of this and i'll show you why because we're going to
i'll show you why because we're going to talk about state normalization
talk about state normalization and just using normalized data overall
and just using normalized data overall which is recommended
which is recommended and then after this i've got this last
and then after this i've got this last line to remove here
line to remove here after this
after this we'll quickly discuss all of the
we'll quickly discuss all of the benefits okay normalized state structure
benefits okay normalized state structure is a recommended approach for storing
is a recommended approach for storing items and normalization means no
items and normalization means no duplication of data and it also means
duplication of data and it also means keeping the items stored in a lookup
keeping the items stored in a lookup table by item id
table by item id so our normalized state shape is
so our normalized state shape is comprised of an object with an ids array
comprised of an object with an ids array and then a nested entities object that
and then a nested entities object that contains all of the items
contains all of the items and the best part of using normalized
and the best part of using normalized data with redux toolkit is that redux
data with redux toolkit is that redux toolkit offers a create entity adapter
toolkit offers a create entity adapter api and that will make your slices less
api and that will make your slices less complicated and easier to manage let's
complicated and easier to manage let's get started with normalize state back in
get started with normalize state back in the post slice file so we'll have to go
the post slice file so we'll have to go back up to where the imports are and you
back up to where the imports are and you can see i'm getting kind of a long line
can see i'm getting kind of a long line here i'll press ctrl b again for all the
here i'll press ctrl b again for all the imports from redux js toolkit and so
imports from redux js toolkit and so instead of that i'll just paste in the
instead of that i'll just paste in the difference where i put them on each line
difference where i put them on each line you can see we've got the three we were
you can see we've got the three we were already using but then i'm also adding
already using but then i'm also adding the create entity adapter okay next
the create entity adapter okay next under our post url
under our post url i'm going to paste this in but it's a
i'm going to paste this in but it's a posts adapter that we're going to create
posts adapter that we're going to create and here we have the create entity
and here we have the create entity adapter and we can put a sort comparer
adapter and we can put a sort comparer function inside of the create entity
function inside of the create entity adapter now this should look familiar
adapter now this should look familiar because it's kind of like what we're
because it's kind of like what we're using inside of the post list so if i
using inside of the post list so if i open the file tree quickly look at the
open the file tree quickly look at the post list we were previously applying a
post list we were previously applying a sort that looked much like that right
sort that looked much like that right here inside the component so one thing i
here inside the component so one thing i like about this already is we're
like about this already is we're abstracting this
abstracting this back to the slice instead of doing that
back to the slice instead of doing that logic in the component so now let's go
logic in the component so now let's go back to the slice again and you can see
back to the slice again and you can see that here where it does the sorting
that here where it does the sorting let's scroll just a little bit and now
let's scroll just a little bit and now instead of just our initial state and
instead of just our initial state and i'm going to select down here through
i'm going to select down here through post as well we're going to have
post as well we're going to have the post adapter dot get initial state
the post adapter dot get initial state for the initial state and notice i got
for the initial state and notice i got rid of the empty array that was posts
rid of the empty array that was posts because our initial state will already
because our initial state will already even if we didn't put anything else in
even if we didn't put anything else in it it will already return that
it it will already return that normalized
normalized object that i was talking about where
object that i was talking about where you have an array of the item ids and
you have an array of the item ids and then you have that entities object that
then you have that entities object that will actually have all the items so
will actually have all the items so that's there automatically and this is
that's there automatically and this is the extra state we're adding on top of
the extra state we're adding on top of that and now we may need to change some
that and now we may need to change some of our reducers and other functions the
of our reducers and other functions the async thunks are just fine so let's
async thunks are just fine so let's scroll down and let's look at how we get
scroll down and let's look at how we get the existing posts for our reaction
the existing posts for our reaction added here we're using state.post.find
added here we're using state.post.find and we'll be able to change that so now
and we'll be able to change that so now it's going to be
it's going to be state.entities and we're passing in that
state.entities and we're passing in that post id because we're using this as an
post id because we're using this as an object lookup so the entities is an
object lookup so the entities is an object and then we're passing in the id
object and then we're passing in the id to look up that specific post and now as
to look up that specific post and now as we scroll down here into the builder
we scroll down here into the builder cases there are several to look at and
cases there are several to look at and we're going to specifically be looking
we're going to specifically be looking at the fulfilled cases so when we get
at the fulfilled cases so when we get down here instead of the state.post
down here instead of the state.post equaling
equaling state.post.concat and the loaded posts
state.post.concat and the loaded posts we're going to change this now because
we're going to change this now because this post adapter has its own crud
this post adapter has its own crud methods so let's look at the first one
methods so let's look at the first one which is upsert mini and we just pass in
which is upsert mini and we just pass in the state and then the loaded post now
the state and then the loaded post now let's scroll down to the add new post
let's scroll down to the add new post where we have the fulfilled here and
where we have the fulfilled here and once again instead of
once again instead of state.post.push i'll select that
state.post.push i'll select that and this has its own method as well so
and this has its own method as well so it's postadapter.add1
it's postadapter.add1 [Music]
[Music] and we pass in the state and the action
and we pass in the state and the action payload which is the new post now we're
payload which is the new post now we're looking at updatepost.fulfilled
looking at updatepost.fulfilled and as we get down here instead of
and as we get down here instead of setting the state.posts equal to this
setting the state.posts equal to this new array where we spread in the posts
new array where we spread in the posts in the action payload we can use
in the action payload we can use postadapter.upcert
postadapter.upcert pass in the state and the action payload
pass in the state and the action payload once again and finally for the delete
once again and finally for the delete post fulfilled instead of state.post
post fulfilled instead of state.post equals posts
equals posts we'll just
we'll just highlight that part and the adapter dot
highlight that part and the adapter dot remove one pass in the state and the id
remove one pass in the state and the id so now you've noticed of course there's
so now you've noticed of course there's a line or two that we're not using we're
a line or two that we're not using we're not using this post line right here and
not using this post line right here and actually if you didn't want to
actually if you didn't want to destructure the id you could say
destructure the id you could say action.payload.id here and just have it
action.payload.id here and just have it right there instead of that line but i
right there instead of that line but i kind of like just having it down to the
kind of like just having it down to the id myself
id myself also here in the update we no longer
also here in the update we no longer need to define posts as well because we
need to define posts as well because we are just getting it from the action
are just getting it from the action payload there as well and here we're not
payload there as well and here we're not using this id we destructured at all
using this id we destructured at all either so we can remove that i believe
either so we can remove that i believe the rest is fine let me double check as
the rest is fine let me double check as i scroll up everything else yep looks
i scroll up everything else yep looks good
good so with that we now need to scroll down
so with that we now need to scroll down to the selectors area i'm going to save
to the selectors area i'm going to save the changes we've made so far and we'll
the changes we've made so far and we'll be replacing some of these selectors
be replacing some of these selectors because
because get selectors is another method we're
get selectors is another method we're going to call that automatically creates
going to call that automatically creates some selectors that we would typically
some selectors that we would typically need one of those would be the select
need one of those would be the select all posts so we can remove this and the
all posts so we can remove this and the other one would be select post by id so
other one would be select post by id so we can remove that as well
we can remove that as well and then it's going to give us one new
and then it's going to give us one new selector i'll paste this in and we'll
selector i'll paste this in and we'll take a look so here again git selectors
take a look so here again git selectors creates these selectors then we're using
creates these selectors then we're using es6 destructuring to give them aliases
es6 destructuring to give them aliases so they match up with our pre-existing
so they match up with our pre-existing code so get selectors create select all
code so get selectors create select all select by id and then select ids
select by id and then select ids we're going to of course name them
we're going to of course name them select all posts that we already had
select all posts that we already had select post by id that we already had
select post by id that we already had and then just to stick with that naming
and then just to stick with that naming convention here we'll say select post
convention here we'll say select post ids
ids notice we do need to pass in a simple
notice we do need to pass in a simple state selector here and we can do that
state selector here and we can do that with an anonymous function so you do
with an anonymous function so you do have to pass in a selector that returns
have to pass in a selector that returns the post slice of state right there so
the post slice of state right there so post adapter dot get selectors
post adapter dot get selectors pass in a selector for the state but
pass in a selector for the state but then it creates these three that we can
then it creates these three that we can export with these aliases that we are
export with these aliases that we are assigning using destructuring i'll save
assigning using destructuring i'll save and i want to say we're finished but vs
and i want to say we're finished but vs code is telling me there's an error up
code is telling me there's an error up there so i really want to check and see
there so i really want to check and see what i did that might have created a
what i did that might have created a problem and now i see the issue exports
problem and now i see the issue exports underlined here because we have our get
underlined here because we have our get initial state and then i just had a
initial state and then i just had a curly brace at the end so if we put a
curly brace at the end so if we put a parenthesis around that
parenthesis around that should be good now that's quite a few
should be good now that's quite a few changes to the post slice to put this
changes to the post slice to put this create entity adapter into action
create entity adapter into action however once you get the hang of
however once you get the hang of applying this post adapter it sure made
applying this post adapter it sure made things a lot easier especially down here
things a lot easier especially down here where we applied the crud methods it
where we applied the crud methods it also made it very easy to get the
also made it very easy to get the existing post here for reaction added as
existing post here for reaction added as we got it from the entities object
we got it from the entities object lookup but then all of these different
lookup but then all of these different cred methods from upsert many and then
cred methods from upsert many and then we had add one
we had add one and then upsert one and eventually
and then upsert one and eventually remove one all of those make that pretty
remove one all of those make that pretty easy to work with
easy to work with now there are more methods and i'll make
now there are more methods and i'll make sure to link to those in the description
sure to link to those in the description or at least the documentation for those
or at least the documentation for those in the description and now we need to
in the description and now we need to make a couple of changes in the post
make a couple of changes in the post list component to take advantage of the
list component to take advantage of the changes we just made in the post slice
changes we just made in the post slice so right up here at the top with the
so right up here at the top with the imports now instead of select all posts
imports now instead of select all posts we're going to select the post ids
we're going to select the post ids so now we have select post ids and now
so now we have select post ids and now we're going to change this post that we
we're going to change this post that we have with use selector all posts which
have with use selector all posts which we're no longer importing and we're
we're no longer importing and we're going to define our ordered post ids
going to define our ordered post ids right here
right here using the use selector and pass in the
using the use selector and pass in the select post ids and then in the
select post ids and then in the succeeded block here of our conditional
succeeded block here of our conditional with the if and loading status and then
with the if and loading status and then succeeded and then finally failed
succeeded and then finally failed we'll change what we have here because
we'll change what we have here because remember we're doing that sort compare
remember we're doing that sort compare function already inside the create
function already inside the create entity adapter that's inside the post
entity adapter that's inside the post slice we no longer need to sort here and
slice we no longer need to sort here and we'll set the content just a little bit
we'll set the content just a little bit differently because we're using the
differently because we're using the ordered post ids we'll map over that and
ordered post ids we'll map over that and we'll pass in post id so let's save
we'll pass in post id so let's save these changes and now go to our post
these changes and now go to our post excerpt that we did have the react memo
excerpt that we did have the react memo on but we'll just make a few changes
on but we'll just make a few changes here as well so now it's not just
here as well so now it's not just getting the post it's getting the post
getting the post it's getting the post id and we also need to go ahead and
id and we also need to go ahead and import a couple of things so let's put
import a couple of things so let's put the imports here we'll have the use
the imports here we'll have the use selector and the select post by id
selector and the select post by id selector that we've created and then
selector that we've created and then inside the component we'll put those to
inside the component we'll put those to work
work by calling well we'll have you selector
by calling well we'll have you selector here and then we'll call the select post
here and then we'll call the select post by id when we pass in the state and the
by id when we pass in the state and the post id that we received as a prop after
post id that we received as a prop after that we'll have our post defined and
that we'll have our post defined and everything in the jsx should work as it
everything in the jsx should work as it was before okay that's a lot of changes
was before okay that's a lot of changes but let's drag vs code back to the left
but let's drag vs code back to the left and let's look at our page i'll clear
and let's look at our page i'll clear out the profiler altogether for now and
out the profiler altogether for now and let's just make sure everything's
let's just make sure everything's working first so let's view a post we've
working first so let's view a post we've got a post here we can edit the post all
got a post here we can edit the post all of that looks good and of course here on
of that looks good and of course here on the homepage we see all of the post
the homepage we see all of the post excerpts as we expect so now let's see
excerpts as we expect so now let's see what happens when we record the profile
what happens when we record the profile and we click on thumbs up three times
and we click on thumbs up three times and now we'll stop the recording once
and now we'll stop the recording once again it only rendered that very first
again it only rendered that very first post excerpt so everything is working as
post excerpt so everything is working as expected with the normalized data we
expected with the normalized data we simplified the post slice and we were
simplified the post slice and we were able to use those adapter crud methods
able to use those adapter crud methods and then it also created some selectors
and then it also created some selectors for us that we destructured and of
for us that we destructured and of course using aliases renamed what we
course using aliases renamed what we already had in our code but we
already had in our code but we simplified our code we pulled more logic
simplified our code we pulled more logic out of the components put it in the post
out of the components put it in the post slice and now this optimization
slice and now this optimization stood the test of time here as far as
stood the test of time here as far as rendering all of our
rendering all of our post excerpts and only re-rendering the
post excerpts and only re-rendering the one that got the reaction so those are
one that got the reaction so those are some good optimizations to add into your
some good optimizations to add into your redux toolkit arsenal
redux toolkit arsenal i'm providing a beginner's example of
i'm providing a beginner's example of rtk query we'll build a simple react
rtk query we'll build a simple react crud app with rtk query and i think you
crud app with rtk query and i think you will see it is very easy to use i'm
will see it is very easy to use i'm going to move at a slightly faster pace
going to move at a slightly faster pace today since i don't expect you to be a
today since i don't expect you to be a react beginner being a beginner with rtk
react beginner being a beginner with rtk query is totally expected and that's
query is totally expected and that's what we're going to work through okay
what we're going to work through okay let's look at the package json first and
let's look at the package json first and you can see the dependencies i've got
you can see the dependencies i've got here the first three
here the first three are for font awesome and i'm using font
are for font awesome and i'm using font awesome to create some icons that are
awesome to create some icons that are actually rendered as components and
actually rendered as components and you'll see that in the code if you
you'll see that in the code if you haven't done that before i'll leave a
haven't done that before i'll leave a link to how to do that in the
link to how to do that in the description very easy but you need these
description very easy but you need these three dependencies and so while we're
three dependencies and so while we're not covering that today that's part of
not covering that today that's part of it then of course we've already got
it then of course we've already got redux js slash toolkit that dependency
redux js slash toolkit that dependency here as well the one to really note
here as well the one to really note today is react has upgraded to
today is react has upgraded to version 18 now so that does make a
version 18 now so that does make a change from what you may be used to
change from what you may be used to seeing in the index file we won't really
seeing in the index file we won't really use any of those features today so much
use any of those features today so much but we're using the new version so
but we're using the new version so before we might have had react dom dot
before we might have had react dom dot render and notice react dom is now being
render and notice react dom is now being imported from react dom slash client
imported from react dom slash client instead of just react dom if you don't
instead of just react dom if you don't do that you'll get a warning
do that you'll get a warning and then we're using create root here
and then we're using create root here and putting the document get element by
and putting the document get element by id right here and then we're just
id right here and then we're just chaining the dot render on after that so
chaining the dot render on after that so some very small changes just due to
some very small changes just due to react version 18 that you see in the
react version 18 that you see in the index js but not covering react 18 today
index js but not covering react 18 today and really it won't impact anything else
and really it won't impact anything else we're doing now also in the starter code
we're doing now also in the starter code here that's available for download from
here that's available for download from the link in the description
the link in the description is a data folder and notice i've got a
is a data folder and notice i've got a db.json and it just has all of these to
db.json and it just has all of these to do's in it and that's because we're
do's in it and that's because we're going to use json server so to install
going to use json server so to install that if you don't already have json
that if you don't already have json server installed now i'm already running
server installed now i'm already running the react app here by the way so we're
the react app here by the way so we're going to just
going to just open a second terminal window
open a second terminal window now to install json server if you don't
now to install json server if you don't have it we're going to install it
have it we're going to install it globally type json server
globally type json server and then you would want well actually to
and then you would want well actually to install it you'd type npm i
install it you'd type npm i json
json server and then dash g that's the global
server and then dash g that's the global install now i've already got it
install now i've already got it installed so i'm not going to press
installed so i'm not going to press enter right now but that's how you would
enter right now but that's how you would install it if you need it
install it if you need it after that to go ahead and start the
after that to go ahead and start the server you type
server you type json-server
json-server and then you'll have dash dash
and then you'll have dash dash watch and then you need to specify where
watch and then you need to specify where your data is well it's in our data
your data is well it's in our data folder and then it's db.json
folder and then it's db.json and then we're going to specify a port
and then we're going to specify a port which is port 3500 and then press enter
which is port 3500 and then press enter it will identify our to-do's there and
it will identify our to-do's there and it starts watching that data so now it
it starts watching that data so now it will support create read update and
will support create read update and delete functions okay now that i've got
delete functions okay now that i've got that running and i like i said i have
that running and i like i said i have the app running over here in the other
the app running over here in the other terminal window i'm just going to close
terminal window i'm just going to close the terminal window for now and close
the terminal window for now and close this db.json and let's take a quick look
this db.json and let's take a quick look at the app.js and you can see here we're
at the app.js and you can see here we're importing a to-do list component that is
importing a to-do list component that is in a features directory and then a
in a features directory and then a to-do's directory and then there's our
to-do's directory and then there's our to-do list component and this is how you
to-do list component and this is how you typically organize features when you're
typically organize features when you're using redux so that's the reason for
using redux so that's the reason for that file structure if you're not
that file structure if you're not familiar with redux okay and then we're
familiar with redux okay and then we're just returning that to-do list component
just returning that to-do list component here in the app component so really
here in the app component so really nothing else going on so let's break
nothing else going on so let's break this out and look at that to-do list
this out and look at that to-do list component now what we don't have here is
component now what we don't have here is any integration with rtk query yet but
any integration with rtk query yet but other than that you may have created a
other than that you may have created a to-do list before if not we'll have the
to-do list before if not we'll have the basic code together for one today but
basic code together for one today but we're still going to add some imports
we're still going to add some imports here for rtk query
here for rtk query we're going to handle a submit and
we're going to handle a submit and handle adding a new to do
handle adding a new to do and then as we scroll on down here you
and then as we scroll on down here you can see the form we have and that's for
can see the form we have and that's for adding that new to do and of course
adding that new to do and of course we're using state here so we have new to
we're using state here so we have new to do and set new to do
do and set new to do other than that we're going to create
other than that we're going to create some content
some content based on conditionals conditional
based on conditionals conditional content and then we'll render that
content and then we'll render that content here in the jsx so that's all
content here in the jsx so that's all the starter code now let's get started
the starter code now let's get started by integrating rtk query into our
by integrating rtk query into our project we'll start by adding an api
project we'll start by adding an api directory inside of the features
directory inside of the features directory so i'll click the new folder
directory so i'll click the new folder up there and we'll name this api which
up there and we'll name this api which is also the default if we were to name
is also the default if we were to name this something else we would have to
this something else we would have to specify that for rtk query so i'll leave
specify that for rtk query so i'll leave it as the default today which also makes
it as the default today which also makes sense it's the representing the api in
sense it's the representing the api in our code
our code now let's add a file to this api
now let's add a file to this api directory it will be called api slice
directory it will be called api slice with camelcase a capital s and then dot
with camelcase a capital s and then dot js
js okay inside the api slice
okay inside the api slice this is where we will create our methods
this is where we will create our methods to interact with the api it essentially
to interact with the api it essentially replaces something like axios and pulls
replaces something like axios and pulls that code out of our component logic and
that code out of our component logic and over here in a separate api slice which
over here in a separate api slice which is kind of how we name things in redux
is kind of how we name things in redux if you're familiar with redux and if
if you're familiar with redux and if you've gone through my redux toolkit
you've gone through my redux toolkit series okay i'm going to paste in the
series okay i'm going to paste in the imports and you can see we've got create
imports and you can see we've got create api
api and fetch based query being imported
and fetch based query being imported from redux js toolkit query react and so
from redux js toolkit query react and so yes this is specific to react you can
yes this is specific to react you can use redux toolkit and rtk query without
use redux toolkit and rtk query without using react but this of course this
using react but this of course this imports some tools specifically for
imports some tools specifically for react now i'm going to paste in the
react now i'm going to paste in the slice and you can see it's exports so we
slice and you can see it's exports so we can export the slice export const api
can export the slice export const api slice and then we use create api
slice and then we use create api inside of this it's an object as you can
inside of this it's an object as you can see with the curly braces the first
see with the curly braces the first thing we do is define the reducer path
thing we do is define the reducer path again
again this is the default so if we didn't put
this is the default so if we didn't put this here it would still be okay because
this here it would still be okay because it would just default to that but i'm
it would just default to that but i'm going ahead and including it and again
going ahead and including it and again you would need to rename that if that is
you would need to rename that if that is not what you were calling it
not what you were calling it now then we have a base query and this
now then we have a base query and this uses the fetch based query that we
uses the fetch based query that we imported and then there's a base url
imported and then there's a base url this should look very familiar to you if
this should look very familiar to you if you're familiar with axios because you
you're familiar with axios because you can define a base url with axios as well
can define a base url with axios as well today we're using json server with our
today we're using json server with our local dev environment so it is just our
local dev environment so it is just our local host and then port 3500 as we
local host and then port 3500 as we specified for json server from there
specified for json server from there we're defining endpoints for the api to
we're defining endpoints for the api to interact with
interact with and if you did work through my redux
and if you did work through my redux toolkit series then you are familiar
toolkit series then you are familiar with the builder cases that we had in
with the builder cases that we had in redux toolkit and this is very similar
redux toolkit and this is very similar so we once again pass in a builder and
so we once again pass in a builder and then we're defining methods to interact
then we're defining methods to interact with the api so we're going to get all
with the api so we're going to get all of the to do's so i'm just naming this
of the to do's so i'm just naming this get to do's and we have builder
get to do's and we have builder dot query and then inside of that we
dot query and then inside of that we have our query method and it once again
have our query method and it once again is just an anonymous function that
is just an anonymous function that passes the slash to do's that would be
passes the slash to do's that would be attached to the base url it's going to
attached to the base url it's going to request then all of the to do's with an
request then all of the to do's with an http get method and then one very cool
http get method and then one very cool feature about rtk query is it creates
feature about rtk query is it creates custom hooks
custom hooks based on the methods that we provide so
based on the methods that we provide so we could name this something else like
we could name this something else like get pizzas or something like that and it
get pizzas or something like that and it would create these custom hooks based on
would create these custom hooks based on that name so this says use get to do's
that name so this says use get to do's query but if we named this get pizzas it
query but if we named this get pizzas it would be use get pizza's query so it's
would be use get pizza's query so it's going to start with use and end with
going to start with use and end with query and it's going to use whatever
query and it's going to use whatever name we use for the method in between so
name we use for the method in between so down here we've just got export const
down here we've just got export const and we're destructuring getting the use
and we're destructuring getting the use get to do's query from api slice and now
get to do's query from api slice and now before we put this custom hooked use
before we put this custom hooked use inside of our to-do list component i'll
inside of our to-do list component i'll save this file we need to go back to the
save this file we need to go back to the index.js some might do this in the
index.js some might do this in the app.js but it's just like the context
app.js but it's just like the context provider if you were using the context
provider if you were using the context api with react we need to provide our
api with react we need to provide our slice to the app so there's a couple of
slice to the app so there's a couple of imports we need to use here and we're
imports we need to use here and we're importing the api provider once again
importing the api provider once again from redux js toolkit query and react
from redux js toolkit query and react and then we're importing that api slice
and then we're importing that api slice that we created and exported so it's
that we created and exported so it's from features
from features api and then we're getting the api slice
api and then we're getting the api slice so once we have those we need to wrap
so once we have those we need to wrap our app with that provider and i'll do
our app with that provider and i'll do that just by highlighting the app and
that just by highlighting the app and then pasting this over so you can see
then pasting this over so you can see but we're absolutely wrapping this app
but we're absolutely wrapping this app component in the api provider and then
component in the api provider and then we're passing in the api to the api or
we're passing in the api to the api or with the api provider and it is of
with the api provider and it is of course the api slice that we created and
course the api slice that we created and now that our app can access this we can
now that our app can access this we can put that hook to use that we created so
put that hook to use that we created so let's go to the to-do list component at
let's go to the to-do list component at the very top where i noted add imports
the very top where i noted add imports with a comma or a comment i'm going to
with a comma or a comment i'm going to just paste in this import and it is the
just paste in this import and it is the use get to do's query that we created
use get to do's query that we created right here so then we need to define
right here so then we need to define that or use it inside of the component
that or use it inside of the component and we'll do that by just pasting this
and we'll do that by just pasting this in and let's look at everything we get
in and let's look at everything we get from this hook which is quite a bit
from this hook which is quite a bit we're getting data and we're
we're getting data and we're destructuring all of this and i'm
destructuring all of this and i'm renaming the data to do's here and then
renaming the data to do's here and then we have is loading is success is error
we have is loading is success is error and finally of course if there is an
and finally of course if there is an error we find out what that error is so
error we find out what that error is so this looks a lot like a custom use axios
this looks a lot like a custom use axios hook or some other logic you may have
hook or some other logic you may have seen used in a component before and once
seen used in a component before and once again this custom hook is being created
again this custom hook is being created for us so that's pretty awesome with rtk
for us so that's pretty awesome with rtk query now let's go ahead and use this to
query now let's go ahead and use this to conditionally render some content i'm
conditionally render some content i'm going to scroll down and where we find
going to scroll down and where we find our content here and i left a comment
our content here and i left a comment that said define conditional content
that said define conditional content i'll just paste this in quickly and
i'll just paste this in quickly and we'll break it down we've got if is
we'll break it down we've got if is loading so if that's true we're just
loading so if that's true we're just going to render this loading paragraph
going to render this loading paragraph and if you have a spinner component
and if you have a spinner component that's a great place to put it as well
that's a great place to put it as well else if
else if is success meaning we've received that
is success meaning we've received that data for now we're just going to use
data for now we're just going to use json stringify and have it render to the
json stringify and have it render to the page so it won't look pretty but we'll
page so it won't look pretty but we'll know we've got it and then the final
know we've got it and then the final else if here is is error and then if
else if here is is error and then if that is true of course we have an error
that is true of course we have an error and we're going to display what that
and we're going to display what that error is and you can see in the jsx
error is and you can see in the jsx we're just going to render that content
we're just going to render that content so let's save all of this and now let's
so let's save all of this and now let's pull this over to the left visual studio
pull this over to the left visual studio code that is and see what this looks
code that is and see what this looks like okay we've got an error it looks
like okay we've got an error it looks like an import is wrong where i've got
like an import is wrong where i've got dot dot slash api slice so let's see
dot dot slash api slice so let's see what's going on i'll pull this back over
what's going on i'll pull this back over so i can see the full thing and we'll
so i can see the full thing and we'll need to scroll up to the top
need to scroll up to the top and yeah that's probably not where that
and yeah that's probably not where that is so let's find our api slice we needed
is so let's find our api slice we needed to go
to go up out of the to-do's
up out of the to-do's two dots not two slashes and then we
two dots not two slashes and then we need to go into the api folder
need to go into the api folder then find the api slice and we were
then find the api slice and we were missing that api folder there in the
missing that api folder there in the import okay we should be good i'll drag
import okay we should be good i'll drag this back to the left
this back to the left and yep we're getting all of that json
and yep we're getting all of that json stringify data here on the page so we
stringify data here on the page so we are receiving all of the data okay let's
are receiving all of the data okay let's pull visual studio code back over so we
pull visual studio code back over so we can view it in a full screen and now
can view it in a full screen and now that we know we're receiving the data
that we know we're receiving the data let's go back to that api slice and add
let's go back to that api slice and add our other methods okay we'll put a comma
our other methods okay we'll put a comma right after this get to do's method and
right after this get to do's method and we can paste in our next method here
we can paste in our next method here and that would be an add to do and
and that would be an add to do and notice something different about it
notice something different about it instead of a builder.query
instead of a builder.query it is a builder dot mutation and the
it is a builder dot mutation and the rest of our methods will be mutations
rest of our methods will be mutations and that means we're actually changing
and that means we're actually changing the data we're not just requesting or
the data we're not just requesting or querying the data but then we'll still
querying the data but then we'll still have the keyword query right here and
have the keyword query right here and notice a to-do is being passed in
notice a to-do is being passed in because it needs a new to do
because it needs a new to do and then we're once again specifying a
and then we're once again specifying a url but this time we're saying it is the
url but this time we're saying it is the url instead of just having a default
url instead of just having a default query like we did above we're also
query like we did above we're also saying what method we're using because
saying what method we're using because it could be different it could be put or
it could be different it could be put or patch or delete or like we have here is
patch or delete or like we have here is post and then for the body of this
post and then for the body of this request we're just passing in that new
request we're just passing in that new to do okay after the add to do let's go
to do okay after the add to do let's go ahead and paste in the update to do and
ahead and paste in the update to do and look how it is very similar to the add
look how it is very similar to the add to do it's also a builder mutation it
to do it's also a builder mutation it also receives a to do but notice the url
also receives a to do but notice the url is different here we're using a template
is different here we're using a template literal so we can specify the specific
literal so we can specify the specific to do with its id that we're going to
to do with its id that we're going to update and we're using patch and not put
update and we're using patch and not put you could use either one put is
you could use either one put is typically used as the method when you're
typically used as the method when you're replacing the
replacing the full record and patches typically when
full record and patches typically when you're just updating part of the record
you're just updating part of the record so i'm using patch right here
so i'm using patch right here we are passing in the to do though and
we are passing in the to do though and then after that let's go ahead and put
then after that let's go ahead and put in the delete and to do that i'm going
in the delete and to do that i'm going to scroll a little bit so we can see it
to scroll a little bit so we can see it all and here is our delete to do once
all and here is our delete to do once again it's a mutation now we only need
again it's a mutation now we only need the id whereas the update needed not
the id whereas the update needed not only the to do id but also the to do
only the to do id but also the to do itself here we just need the id so we're
itself here we just need the id so we're destructuring that from the to do as
destructuring that from the to do as it's passed in
it's passed in or whatever object we send with the id
or whatever object we send with the id and then we're passing in that same url
and then we're passing in that same url essentially but now we don't have to
essentially but now we don't have to have to do dot id it just has the id
have to do dot id it just has the id here in the template literal the method
here in the template literal the method is delete and the body only contains the
is delete and the body only contains the id because that's all that is needed to
id because that's all that is needed to delete the to-do and now that we've
delete the to-do and now that we've added these new methods we can just
added these new methods we can just scroll down here to our export const and
scroll down here to our export const and we just need to add those other hooks
we just need to add those other hooks that are created and notice once again
that are created and notice once again they're not queries they are all
they're not queries they are all mutations so they start with u's and end
mutations so they start with u's and end with mutations so we created an add to
with mutations so we created an add to do method and so it's use add to do
do method and so it's use add to do mutation the same for use update to do
mutation the same for use update to do mutation and use delete to do mutation
mutation and use delete to do mutation okay let's save these and head back to
okay let's save these and head back to the to do list to use all of these new
the to do list to use all of these new hooks so instead of just the use to do's
hooks so instead of just the use to do's query being imported we're going to
query being imported we're going to import in the other three hooks that
import in the other three hooks that were created as well and then under
were created as well and then under where we use the use get to do's query
where we use the use get to do's query hook
hook we'll paste these in and you can see
we'll paste these in and you can see we're just getting the functions from
we're just getting the functions from these hooks we don't really need to wait
these hooks we don't really need to wait on the is loading is success is error
on the is loading is success is error and all of those things that we get from
and all of those things that we get from the query when we're reading the data
the query when we're reading the data this is something we're actually doing
this is something we're actually doing to the data so add to do update to do
to the data so add to do update to do and delete to do and now the first
and delete to do and now the first function we'll put to work is that add
function we'll put to work is that add to do so right here inside of the handle
to do so right here inside of the handle submit
submit i'll paste this in and let's take a look
i'll paste this in and let's take a look we've got the add to do and all it
we've got the add to do and all it really expects to receive is a to do so
really expects to receive is a to do so i'm creating a to do object here
i'm creating a to do object here we're passing in the new to do we're
we're passing in the new to do we're setting the completed defaults and i'm
setting the completed defaults and i'm just setting them all to user id 1. if
just setting them all to user id 1. if you wanted to create a drop menu and
you wanted to create a drop menu and provide different user ids you could the
provide different user ids you could the data has user ids in it so that's really
data has user ids in it so that's really up to you and how you want to do it
up to you and how you want to do it right now the way this is set up every
right now the way this is set up every new to do that is added would be
new to do that is added would be attributed to user one and now let's add
attributed to user one and now let's add some more detail to our conditional
some more detail to our conditional content so where we have the json
content so where we have the json stringify let's replace that and map
stringify let's replace that and map over all of the to do's to create
over all of the to do's to create something that's a little bit more like
something that's a little bit more like we want i'll hide the file tree so we
we want i'll hide the file tree so we can see it all but what we're doing is
can see it all but what we're doing is mapping over all of the to do's instead
mapping over all of the to do's instead of the json stringify here and then
of the json stringify here and then we're returning
we're returning an article and each article is going to
an article and each article is going to have a key that matches the to do dot id
have a key that matches the to do dot id because there's lots of articles that
because there's lots of articles that will be rendered on the page one for
will be rendered on the page one for each to do
each to do and then we've got a div here with a
and then we've got a div here with a class name of to do and that holds the
class name of to do and that holds the input and then that is the checkbox and
input and then that is the checkbox and then it also holds the label which is
then it also holds the label which is the description and that label has the
the description and that label has the html4 which we're also assigning to the
html4 which we're also assigning to the id of the input so they're linked and
id of the input so they're linked and using a label here instead of a span or
using a label here instead of a span or a paragraph really helps with
a paragraph really helps with accessibility as well because it's
accessibility as well because it's linked to that checkbox other than that
linked to that checkbox other than that when we change we're calling the update
when we change we're calling the update to do and what we do there is spread in
to do and what we do there is spread in the existing to do then we overwrite the
the existing to do then we overwrite the completed state because this change is
completed state because this change is for the check box and so that just sets
for the check box and so that just sets the completed state to
the completed state to false if it was true or true if it was
false if it was true or true if it was false and then of course we have a
false and then of course we have a button here and the button has the trash
button here and the button has the trash can icon
can icon and that calls the delete to do and
and that calls the delete to do and we're just passing in an object with
we're just passing in an object with that id so we've got id and then to do
that id so we've got id and then to do dot id right here okay with these
dot id right here okay with these changes saved let's pull our code back
changes saved let's pull our code back over and take a look at our app well
over and take a look at our app well this looks much better so let's see what
this looks much better so let's see what happens if we go ahead and click on
happens if we go ahead and click on things
things it's not changing is it it's not
it's not changing is it it's not updating
updating see if it deletes
see if it deletes doesn't seem to be deleting i wonder
doesn't seem to be deleting i wonder what's going on maybe we can add a new
what's going on maybe we can add a new to-do and we'll say
to-do and we'll say learn stuff
learn stuff and let's see if it's added it will be
and let's see if it's added it will be all the way at the bottom
all the way at the bottom it's not at the bottom either so let's
it's not at the bottom either so let's talk about what's going on i actually
talk about what's going on i actually know what's going on but we needed to
know what's going on but we needed to create this situation to understand it
create this situation to understand it so back in the api slice
so back in the api slice if we look at these
if we look at these what is happening is the results get
what is happening is the results get cached and we're not invalidating the
cached and we're not invalidating the previous cache and so it's not updating
previous cache and so it's not updating to show the new changes whether that's a
to show the new changes whether that's a delete an update or even a new
delete an update or even a new to-do list or not a new to-do list a new
to-do list or not a new to-do list a new to-do item added to the to-do list it's
to-do item added to the to-do list it's not showing any of that because we're
not showing any of that because we're still seeing the cached version of the
still seeing the cached version of the data what we need to do is assign a tag
data what we need to do is assign a tag to the cache and then let it know which
to the cache and then let it know which mutations invalidate the cache and so
mutations invalidate the cache and so then it will automatically refetch that
then it will automatically refetch that data for us so the first thing we're
data for us so the first thing we're going to do after the base query here is
going to do after the base query here is put in tag types and we're going to name
put in tag types and we're going to name this to do's and then for our get to
this to do's and then for our get to do's method that we have here
do's method that we have here we need to put in a provides tags and
we need to put in a provides tags and say it's providing this tag of to do's
say it's providing this tag of to do's so then we'll need to invalidate the to
so then we'll need to invalidate the to do's cache
do's cache when we use these builder mutations
when we use these builder mutations below whether we're creating a new to do
below whether we're creating a new to do updating or deleting and i'll scroll
updating or deleting and i'll scroll just a little bit but we can add those
just a little bit but we can add those right here by putting a comma after the
right here by putting a comma after the query inside the mutation and then
query inside the mutation and then saying invalidates tags to do's and so
saying invalidates tags to do's and so let's do that for each one of these
let's do that for each one of these so we know the change has been made
so we know the change has been made actually let's just do it for the update
actually let's just do it for the update and the create and not the delete and
and the create and not the delete and we'll be able to see the difference once
we'll be able to see the difference once again so now let's drag this back over
again so now let's drag this back over to the left
to the left and look at our to-do list so for the
and look at our to-do list so for the new one we could now say
new one we could now say learn stuff
learn stuff press enter should work there we go
press enter should work there we go let's see if we have our learn stuff at
let's see if we have our learn stuff at the bottom yep now we've got learn stuff
the bottom yep now we've got learn stuff twice because i typed that earlier with
twice because i typed that earlier with two exclamation marks now we've just got
two exclamation marks now we've just got one
one so let's try the delete
so let's try the delete we're not seeing anything from the
we're not seeing anything from the delete are we because it's not updating
delete are we because it's not updating so it actually did create this earlier
so it actually did create this earlier and it is actually deleting it now but
and it is actually deleting it now but our list is not re-rendering likewise we
our list is not re-rendering likewise we should go ahead and see a re-render of
should go ahead and see a re-render of the list if i update an item yep and now
the list if i update an item yep and now that learn stuff disappeared because it
that learn stuff disappeared because it really isn't in the current state of the
really isn't in the current state of the to do's that we have at the api
to do's that we have at the api however trying to delete something did
however trying to delete something did not cause the list to re-render whereas
not cause the list to re-render whereas updating it did so let's go ahead and
updating it did so let's go ahead and add that mutation
add that mutation back over here as well
back over here as well let's find that we've got the invalidate
let's find that we've got the invalidate tags and that's what we want to add is
tags and that's what we want to add is to that delete mutation so we put the
to that delete mutation so we put the comma there
comma there and put in invalidates tags and save now
and put in invalidates tags and save now we've re-rendered everything
we've re-rendered everything and now if i were to say delete this
and now if i were to say delete this second one here
second one here our list re-renders
our list re-renders and if i were to
and if i were to check then it re-renders and shows that
check then it re-renders and shows that new state as well likewise if i were to
new state as well likewise if i were to say hey for a new item and press enter
say hey for a new item and press enter we should now see it and this also
we should now see it and this also highlights our last problem any new to
highlights our last problem any new to do item we're adding is added at the
do item we're adding is added at the very bottom of the list i'd rather see
very bottom of the list i'd rather see this in reverse order and see my new
this in reverse order and see my new item at the top of the list we can also
item at the top of the list we can also fix this because much like axios
fix this because much like axios rtk query provides a transform response
rtk query provides a transform response so there i can put in my sort function
so there i can put in my sort function and i'm going to drag visual studio code
and i'm going to drag visual studio code back over to see everything for now so
back over to see everything for now so you can see this clearly we've got a
you can see this clearly we've got a transform response right after our query
transform response right after our query and here i'm just passing in the
and here i'm just passing in the response and then i'm calling a basic
response and then i'm calling a basic sort function here for numbers in
sort function here for numbers in javascript because we're using the id
javascript because we're using the id numbers and to sort it in ascending
numbers and to sort it in ascending order it would be a minus b but to sort
order it would be a minus b but to sort in descending it's b minus a
in descending it's b minus a so i'll just save this and now we should
so i'll just save this and now we should be transforming that response that we
be transforming that response that we get from the api and it should be
get from the api and it should be sorting it in reverse order and we've
sorting it in reverse order and we've kept the logic once again out of the
kept the logic once again out of the component and put it over here with the
component and put it over here with the api logic for rtk query i'll pull this
api logic for rtk query i'll pull this to the left and we'll look and now my
to the left and we'll look and now my hay is at the top of the list i can
hay is at the top of the list i can delete that
delete that delete my learn stuff and even the new
delete my learn stuff and even the new to do
to do and then add
and then add another new to do
another new to do and it's right at the top
and it's right at the top so overall you've got a quick
so overall you've got a quick introduction to rtk query here and we've
introduction to rtk query here and we've created
created read update create and delete functions
read update create and delete functions or methods if you will inside of our api
or methods if you will inside of our api slice provided that to our complete
slice provided that to our complete application and then of course
application and then of course implemented those in our to-do list
implemented those in our to-do list component we have a nice little to-do
component we have a nice little to-do list here and we've kept all of this api
list here and we've kept all of this api logic basically out of the components
logic basically out of the components and in our separate api slice
and in our separate api slice i've got a redux blog project here on
i've got a redux blog project here on the left and on the right i've got
the left and on the right i've got chrome dev tools open and we're at the
chrome dev tools open and we're at the network tab now i'm going to click a
network tab now i'm going to click a reaction emoji and when i do we see a
reaction emoji and when i do we see a couple of network requests one's just
couple of network requests one's just the pre-flight request that we see here
the pre-flight request that we see here and then the fetch request to update the
and then the fetch request to update the data but as i continue to click we see
data but as i continue to click we see that the reaction responds immediately
that the reaction responds immediately and then afterwards comes the fetch
and then afterwards comes the fetch request to update the data that's an
request to update the data that's an optimistic update we're going to apply
optimistic update we're going to apply that and more let's get started the
that and more let's get started the starter code for today's tutorial is in
starter code for today's tutorial is in the completed source code from lesson 5
the completed source code from lesson 5 in this redux series when we last worked
in this redux series when we last worked on a react redux blog project and we're
on a react redux blog project and we're transitioning the blog project we
transitioning the blog project we completed with axios and async thunks in
completed with axios and async thunks in lesson 5 to rtk query with normalized
lesson 5 to rtk query with normalized cache state and even some optimistic
cache state and even some optimistic updates you can get a link to that
updates you can get a link to that starter code in the description below
starter code in the description below now up to lesson five we were using the
now up to lesson five we were using the json placeholder fake api but today
json placeholder fake api but today we're going to switch over to json
we're going to switch over to json server and i've already added a data
server and i've already added a data folder up here in our file tree and
folder up here in our file tree and inside that folder is this
inside that folder is this db.json file and you can see i've
db.json file and you can see i've already put some users data in here and
already put some users data in here and there's also post data so once we scroll
there's also post data so once we scroll past the 10 users then we should have
past the 10 users then we should have around 100 posts now i've modified the
around 100 posts now i've modified the data some by already playing around with
data some by already playing around with it but you've basically got 100 posts
it but you've basically got 100 posts here inside of this data and of course
here inside of this data and of course this is with the code that you can
this is with the code that you can download in the description or you can
download in the description or you can go to the json placeholder site like i
go to the json placeholder site like i did and just grab the data that they
did and just grab the data that they have there and paste it into this
have there and paste it into this db.json file but remember if you do that
db.json file but remember if you do that you would be grabbing the users and
you would be grabbing the users and making that one data array and then as
making that one data array and then as you see here i've got posts and it's a
you see here i've got posts and it's a separate data array but you can put it
separate data array but you can put it all within the same file and it just
all within the same file and it just needs to start out as an object so once
needs to start out as an object so once i get here to the top you can see it
i get here to the top you can see it starts out as one large object and
starts out as one large object and that's what json server uses okay now if
that's what json server uses okay now if you don't have json server yet it's not
you don't have json server yet it's not a package you add to your project but
a package you add to your project but you can install it globally like i have
you can install it globally like i have or you could use npx if you're familiar
or you could use npx if you're familiar with that i'll show you what i've done
with that i'll show you what i've done which is npm i for install and then json
which is npm i for install and then json server and then dash g which means
server and then dash g which means globally so you could just start it from
globally so you could just start it from any command line like that i've already
any command line like that i've already installed it so i'm not going to hit
installed it so i'm not going to hit return there but then after you've
return there but then after you've installed it you want to go ahead and
installed it you want to go ahead and start it and to do that it's json server
start it and to do that it's json server then we're going to say dash dash
then we're going to say dash dash watch then we tell it where our data is
watch then we tell it where our data is so it's data
so it's data db.json then i'm going to say what port
db.json then i'm going to say what port i want it to run on and that's 3500
i want it to run on and that's 3500 because it's simulating our back end and
because it's simulating our back end and now i'm going to press return it starts
now i'm going to press return it starts up it sees our users it sees our posts
up it sees our users it sees our posts and it's ready to go so now if i start
and it's ready to go so now if i start our project i'm going to open a separate
our project i'm going to open a separate command line to start our project on
command line to start our project on later on after we make some changes okay
later on after we make some changes okay now we're going to go into our source
now we're going to go into our source folder and inside the source folder
folder and inside the source folder inside the features folder that we have
inside the features folder that we have we're going to create an api folder as
we're going to create an api folder as well so we'll create that api folder and
well so we'll create that api folder and inside of it we'll create a new file
inside of it we'll create a new file called api slice with a capital s is in
called api slice with a capital s is in camel case and then it's dot js once we
camel case and then it's dot js once we have our api slice i'll paste in a
have our api slice i'll paste in a little bit of code and let's discuss
little bit of code and let's discuss what we've got here before we move on so
what we've got here before we move on so we are importing create api
we are importing create api and fetch base query and this comes from
and fetch base query and this comes from redux js toolkit query slash react since
redux js toolkit query slash react since we're using react today
we're using react today and then we say export so we can export
and then we say export so we can export the api slice we define the api slice
the api slice we define the api slice using create api and then here it's an
using create api and then here it's an object inside now this looks a little
object inside now this looks a little different than what you might have seen
different than what you might have seen in my intro to rtk query because notice
in my intro to rtk query because notice we're not defining any endpoints here
we're not defining any endpoints here we're passing a builder in but we
we're passing a builder in but we essentially have no endpoints right here
essentially have no endpoints right here now we need to have this because it's
now we need to have this because it's required but what we're going to do is
required but what we're going to do is create extended slices so we can
create extended slices so we can separate our logic say from posts and
separate our logic say from posts and users for our project and this reducer
users for our project and this reducer path is optional if you name it api
path is optional if you name it api because that's the default if you want
because that's the default if you want to name it something else it's not
to name it something else it's not optional the base query here is a lot
optional the base query here is a lot like axios where we would define a base
like axios where we would define a base query and we use that fetch base query
query and we use that fetch base query that we import and here we provide that
that we import and here we provide that base url today i'm providing localhost
base url today i'm providing localhost 3500. if you were to use this with an
3500. if you were to use this with an api online you would need to put of
api online you would need to put of course that url there the tag types
course that url there the tag types we're going to use with this slice right
we're going to use with this slice right now is post so i'm only putting post
now is post so i'm only putting post there as i'm going to give you examples
there as i'm going to give you examples for the posts and later on i'll let you
for the posts and later on i'll let you complete the users yourself and compare
complete the users yourself and compare that to my completed source code on
that to my completed source code on github okay with the api slice complete
github okay with the api slice complete now we have a lot of work to do inside
now we have a lot of work to do inside of our post slice because this is where
of our post slice because this is where we're going to have our extended api
we're going to have our extended api slice so we can start out now by
slice so we can start out now by removing some things we're going to
removing some things we're going to remove all of those async thunks we
remove all of those async thunks we initially created here so we've got
initially created here so we've got fetch posts add new post
fetch posts add new post update and delete i can just select all
update and delete i can just select all of those and hit backspace to get rid of
of those and hit backspace to get rid of them we're also going to be able to get
them we're also going to be able to get rid of our post url because we're going
rid of our post url because we're going to use what we defined already in our
to use what we defined already in our slice we're not going to use create
slice we're not going to use create async thunk anymore so i can get rid of
async thunk anymore so i can get rid of that and i believe i can even get rid of
that and i believe i can even get rid of create slice so i'll go ahead and do
create slice so i'll go ahead and do that as well we're left with create
that as well we're left with create selector and create entity adapter you
selector and create entity adapter you can see we're no longer going to use
can see we're no longer going to use axios either so removing quite a few
axios either so removing quite a few things right now go ahead and get rid of
things right now go ahead and get rid of that blank line at the top we'll keep
that blank line at the top we'll keep our post adapter we're going to continue
our post adapter we're going to continue to use our create entity adapter we're
to use our create entity adapter we're going to continue to have normalized
going to continue to have normalized state we're going to continue to sort
state we're going to continue to sort the posts right here so we can have them
the posts right here so we can have them in reverse order or the most recent post
in reverse order or the most recent post at the top of our list
at the top of our list we can empty out this initial state
we can empty out this initial state though we no longer need that so let's
though we no longer need that so let's go ahead and just make that an empty one
go ahead and just make that an empty one there and now we need to add to our
there and now we need to add to our imports so i'm just going to put this
imports so i'm just going to put this underneath our import of sub from date
underneath our import of sub from date fns
fns and we're importing in our api slice
and we're importing in our api slice that we created let's make sure we have
that we created let's make sure we have the correct path for that so i'll type
the correct path for that so i'll type it again so we're going to go up out of
it again so we're going to go up out of posts and then we'll go into the api
posts and then we'll go into the api folder and then there is the api slice
folder and then there is the api slice so yep that's right we'll save that
so yep that's right we'll save that get rid of this extra line here and
get rid of this extra line here and really we're going to get rid of our
really we're going to get rid of our post slice all together even though
post slice all together even though we're really still in this post slice
we're really still in this post slice file we'll still use that name because
file we'll still use that name because we're extending the api slice to handle
we're extending the api slice to handle that so i'm going to select everything
that so i'm going to select everything here with the post slice including the
here with the post slice including the extra reducers that we have down here
extra reducers that we have down here and we're in going to end up replacing
and we're in going to end up replacing all of that so i'll hit backspace once
all of that so i'll hit backspace once again and what i'm going to replace it
again and what i'm going to replace it with
with is if i could
is if i could scroll over oh i just missed some of it
scroll over oh i just missed some of it here so what i need is
here so what i need is an export
an export const oh i had the first part of export
const oh i had the first part of export that's what i was doing
that's what i was doing there we go so export const api slice
there we go so export const api slice and now this equals the api slice we
and now this equals the api slice we imported and then you can see we have
imported and then you can see we have dot inject endpoints so this is where we
dot inject endpoints so this is where we will put our endpoints now and that's
will put our endpoints now and that's all going to start with an endpoints
all going to start with an endpoints builder so i can go ahead and put that
builder so i can go ahead and put that in as well so here is our definition for
in as well so here is our definition for endpoints like we're used to seeing in
endpoints like we're used to seeing in the api slice if you completed that
the api slice if you completed that basic intro to rtk query where we
basic intro to rtk query where we created a to-do list you saw this same
created a to-do list you saw this same structure but it was all in the api
structure but it was all in the api slice and you can see the end points are
slice and you can see the end points are also here in the api slice but we just
also here in the api slice but we just didn't do anything with them but you
didn't do anything with them but you have to have them or you'll have an
have to have them or you'll have an error so now we've got the end points
error so now we've got the end points here with the builder and we're ready to
here with the builder and we're ready to define any of our endpoints inside so
define any of our endpoints inside so now i'm going to scroll up so we can see
now i'm going to scroll up so we can see a little bit more of the screen we're
a little bit more of the screen we're going to use and i'm going to paste in
going to use and i'm going to paste in our first endpoint function here now it
our first endpoint function here now it is long enough it took up the whole
is long enough it took up the whole screen so i'll save and let's break this
screen so i'll save and let's break this down so this is git posts meaning we're
down so this is git posts meaning we're going to get all of our post and then we
going to get all of our post and then we have builder dot query as we've seen
have builder dot query as we've seen before in the intro to rtk query so
before in the intro to rtk query so we're just issuing a query here to the
we're just issuing a query here to the slash post and of course this is
slash post and of course this is attached to that base
attached to that base url that we provided in the api slice so
url that we provided in the api slice so if we go back here we see our base url
if we go back here we see our base url of localhost port 3500 so we're
of localhost port 3500 so we're attaching slash posts onto that and just
attaching slash posts onto that and just issuing a get query for those posts but
issuing a get query for those posts but then we're using transform response and
then we're using transform response and we're doing this for a couple of reasons
we're doing this for a couple of reasons here
here and that of course has a function so
and that of course has a function so we've got response data one is the data
we've got response data one is the data that i pulled into that dbjson file
that i pulled into that dbjson file doesn't have
doesn't have the date or the reactions attached to it
the date or the reactions attached to it because i pulled it straight from that
because i pulled it straight from that json placeholder website so if we have
json placeholder website so if we have any of the posts that we received that
any of the posts that we received that don't already have that we need to go
don't already have that we need to go ahead and attach that starter data to
ahead and attach that starter data to them so what i'm doing here is defining
them so what i'm doing here is defining a minute so we can increment that and
a minute so we can increment that and use it for each post so they don't all
use it for each post so they don't all have the exact same time i'm going to
have the exact same time i'm going to hide the file tree control b
hide the file tree control b and we should be able to see more of
and we should be able to see more of this now so then we define loaded posts
this now so then we define loaded posts and this is using map on the response
and this is using map on the response data so we're just creating a new posts
data so we're just creating a new posts array here that we'll be able to use and
array here that we'll be able to use and we're saying if the post doesn't already
we're saying if the post doesn't already have date data then set the post.date to
have date data then set the post.date to this new date and of course each post is
this new date and of course each post is being incremented by a minute so they're
being incremented by a minute so they're all one minute apart same for reactions
all one minute apart same for reactions if the post doesn't have reactions then
if the post doesn't have reactions then we're setting the reactions all to zero
we're setting the reactions all to zero as it first comes in
as it first comes in so that's the first purpose of transform
so that's the first purpose of transform response the second purpose here that we
response the second purpose here that we need to use as we're using rtk query
need to use as we're using rtk query with the entity adapter is to go ahead
with the entity adapter is to go ahead and normalize our state so we need to
and normalize our state so we need to send this new state to the posts adapter
send this new state to the posts adapter and we do that with set all
and we do that with set all and then we pass in the initial state
and then we pass in the initial state and remember we had that initial state
and remember we had that initial state defined already and then we also have
defined already and then we also have loaded posts now if i go up here to the
loaded posts now if i go up here to the initial state we've got the initial
initial state we've got the initial state right there okay and then the
state right there okay and then the loaded post that we defined right here
loaded post that we defined right here so we're passing that into set all and
so we're passing that into set all and that normalizes our data and if you
that normalizes our data and if you remember from a previous tutorial
remember from a previous tutorial normalized data would have an array of
normalized data would have an array of just the ids and then it has an entities
just the ids and then it has an entities array as well and it's really an
array as well and it's really an entity's object that has a bunch of
entity's object that has a bunch of objects in it in each post and then we
objects in it in each post and then we can use
can use that ids array as an object lookup with
that ids array as an object lookup with the entities when we refer to each post
the entities when we refer to each post okay then we've got provides tags and
okay then we've got provides tags and this is a little more complex than we
this is a little more complex than we saw in our basic to-do list example in
saw in our basic to-do list example in the intro so
the intro so what it is is an array that we see
what it is is an array that we see defined right here and the first entry
defined right here and the first entry we're just identifying as list it's type
we're just identifying as list it's type post as all of these will be
post as all of these will be but that just means we're identifying
but that just means we're identifying the list and any time
the list and any time that we invalidate one of these tags it
that we invalidate one of these tags it will re-perform or re-auto-fetch
will re-perform or re-auto-fetch essentially all the posts again so if we
essentially all the posts again so if we want to get the full list we can just
want to get the full list we can just invalidate the list id but what we're
invalidate the list id but what we're also doing now is providing an object
also doing now is providing an object for each separate individual post
for each separate individual post passing the id from the post we're doing
passing the id from the post we're doing that by mapping over the result but
that by mapping over the result but we're also spreading it into individual
we're also spreading it into individual post ids here so this is what we end up
post ids here so this is what we end up with type post and id for each post so
with type post and id for each post so if any one of those post ids are
if any one of those post ids are invalidated it will also
invalidated it will also refetch our list automatically because
refetch our list automatically because this is invalidated and that's what
this is invalidated and that's what provides tags does so that is our full
provides tags does so that is our full method right there for git posts now
method right there for git posts now also if you remember from the intro
also if you remember from the intro lesson the previous lesson to rtk query
lesson the previous lesson to rtk query it generates
it generates hooks so custom hooks already based on
hooks so custom hooks already based on the methods we create above so we have
the methods we create above so we have get posts so it creates
get posts so it creates use get post query and we'll be able to
use get post query and we'll be able to use that in our post list component but
use that in our post list component but before we move on to that component
before we move on to that component let's scroll down and look at our
let's scroll down and look at our selectors now here we have a git
selectors now here we have a git selectors and it creates selectors and
selectors and it creates selectors and we rename them with aliases we're going
we rename them with aliases we're going to leave this alone right here because
to leave this alone right here because we're still going to create all these
we're still going to create all these selectors and rename them with aliases
selectors and rename them with aliases everything below the get selectors here
everything below the get selectors here we're no longer using so we can remove
we're no longer using so we can remove everything you see right here so we'll
everything you see right here so we'll just hit backspace and eliminate that
just hit backspace and eliminate that now i'm going to post a couple of new
now i'm going to post a couple of new selectors or paste a couple of new
selectors or paste a couple of new selectors right here above and let's
selectors right here above and let's break these down let's talk about what
break these down let's talk about what these do so the first one is you see my
these do so the first one is you see my note here it just returns the query
note here it just returns the query result object it doesn't issue the query
result object it doesn't issue the query it returns the result object that we
it returns the result object that we already have from the query so select
already have from the query so select post result equals extended api slice
post result equals extended api slice that we defined above then dot endpoints
that we defined above then dot endpoints because that is an object dot get post
because that is an object dot get post referring to the method and then calling
referring to the method and then calling select right there so we're getting that
select right there so we're getting that result
result object
object but that is the entire result object
but that is the entire result object it's not just the data so then we need
it's not just the data so then we need to use create selector which we had
to use create selector which we had already previously imported to create
already previously imported to create this select post data and if you
this select post data and if you remember create selector receives input
remember create selector receives input function or functions and then has an
function or functions and then has an output function so what we're passing in
output function so what we're passing in as the input function
as the input function is our select post result query and then
is our select post result query and then our output function is taking that
our output function is taking that result
result and then just looking at the data
and then just looking at the data property and that data property holds
property and that data property holds our normalized state object that has the
our normalized state object that has the ids array and then the entities as well
ids array and then the entities as well and now let's scroll just a little bit
and now let's scroll just a little bit because while we're keeping these
because while we're keeping these selectors and renaming them here we need
selectors and renaming them here we need to change
to change how git selectors finds the state
how git selectors finds the state because that has changed so what we're
because that has changed so what we're doing is going we're going to use the
doing is going we're going to use the select post data selector that we have
select post data selector that we have up here so i'll just paste this in and
up here so i'll just paste this in and let's look at what this does we're
let's look at what this does we're passing the state as we were before but
passing the state as we were before but now we're using select post data to say
now we're using select post data to say where the state is and of course it
where the state is and of course it returns our normalized state and that's
returns our normalized state and that's great but it could be null especially
great but it could be null especially the first time the app loads so we want
the first time the app loads so we want to use this knowledge coalescing
to use this knowledge coalescing operator here that says basically if
operator here that says basically if what's on the left is null it's going to
what's on the left is null it's going to return what's on the right and that is
return what's on the right and that is our initial state and so that's the only
our initial state and so that's the only change we need to make there and all
change we need to make there and all these selectors will still be good okay
these selectors will still be good okay let's look at the file tree again
let's look at the file tree again because we've made enough changes we
because we've made enough changes we need to change our store as well so in
need to change our store as well so in the app folder we have storejs
the app folder we have storejs now we no longer have a posts reducer so
now we no longer have a posts reducer so i'm going to remove that
i'm going to remove that and in its place i'm going to import
and in its place i'm going to import that api slice that we have created once
that api slice that we have created once again let's make sure we're in the right
again let's make sure we're in the right place we'd go up out of the app folder
place we'd go up out of the app folder and then into the features folder api
and then into the features folder api folder and then api slice so that does
folder and then api slice so that does look correct and now down here we don't
look correct and now down here we don't have a post reducer what we do have is
have a post reducer what we do have is the api slice so i will paste this in
the api slice so i will paste this in and we'll break this down as well so
and we'll break this down as well so this is going to be dynamically named
this is going to be dynamically named but whatever name we put in that reducer
but whatever name we put in that reducer path remember we named it api
path remember we named it api inside of the api slice and that was
inside of the api slice and that was right here inside of the api slice
right here inside of the api slice optional because that's the default but
optional because that's the default but if you named it something else it could
if you named it something else it could have a different name and so that's why
have a different name and so that's why we just want to make this dynamic right
we just want to make this dynamic right here saying api slice dot reducer path
here saying api slice dot reducer path and then it's computed if you want to
and then it's computed if you want to use that terminology and then we would
use that terminology and then we would have the value over here just saying api
have the value over here just saying api slice dot reducer our comma and then
slice dot reducer our comma and then we're just going to leave the users
we're just going to leave the users reducer as it is for now but now as we
reducer as it is for now but now as we use rtk query with the store there's
use rtk query with the store there's some required middleware so i'll paste
some required middleware so i'll paste this in save for the formatting that
this in save for the formatting that looks right and we'll discuss this what
looks right and we'll discuss this what what this is is middleware here and the
what this is is middleware here and the first thing we need to do is get default
first thing we need to do is get default middleware and that's the middleware
middleware and that's the middleware that is already the default with redux
that is already the default with redux so we just need to make sure we have
so we just need to make sure we have that and this is an array that is
that and this is an array that is returned so then we use concat and now
returned so then we use concat and now we're also adding the api slice dot
we're also adding the api slice dot middleware that we need that api slice
middleware that we need that api slice creates and this middleware from api
creates and this middleware from api slice it manages cache lifetimes and
slice it manages cache lifetimes and expirations and it is required to use it
expirations and it is required to use it when we're using rtk query and an api
when we're using rtk query and an api slice now we've finished changes in the
slice now we've finished changes in the store js but we also need to make some
store js but we also need to make some changes in the index js so we're no
changes in the index js so we're no longer going to use fetch posts we
longer going to use fetch posts we already deleted that async thunk and in
already deleted that async thunk and in its place we're going to import in that
its place we're going to import in that extended api slice once again and let's
extended api slice once again and let's make sure we have the correct route to
make sure we have the correct route to that post slice here
that post slice here to bring in that extended api slice so
to bring in that extended api slice so it's dot slash
it's dot slash features slash
features slash api
api oh it was not api actually it was post
oh it was not api actually it was post slash
slash post slice because we're bringing in the
post slice because we're bringing in the extended api slice that we created in
extended api slice that we created in the post slice okay after we do that
the post slice okay after we do that we're no longer using fetch posts but we
we're no longer using fetch posts but we still want to get the post immediately
still want to get the post immediately at app load time and so i'll just change
at app load time and so i'll just change this we're still going to use
this we're still going to use store.dispatch but now we use the
store.dispatch but now we use the extended api slice
extended api slice remember it's an object so then we go
remember it's an object so then we go dot endpoints dot get posts and we call
dot endpoints dot get posts and we call initiate and it gets that initial data
initiate and it gets that initial data and requested at that point and so then
and requested at that point and so then we can load that data once again as the
we can load that data once again as the app starts up okay with the changes
app starts up okay with the changes we've made up to this point now we're
we've made up to this point now we're ready to go to that post list component
ready to go to that post list component and use the use get post query custom
and use the use get post query custom hook that was generated from our git
hook that was generated from our git posts inside of the post slice where we
posts inside of the post slice where we have the extended api slice so now at
have the extended api slice so now at the top here we'll probably end up with
the top here we'll probably end up with some imports we're not going to use but
some imports we're not going to use but for now i'll just put in the import that
for now i'll just put in the import that i know we are going to use which is use
i know we are going to use which is use get post query
get post query coming from our post slice that's in the
coming from our post slice that's in the same folder so that should just be dot
same folder so that should just be dot slash post slice so now inside the
slash post slice so now inside the component let's go ahead and use this
component let's go ahead and use this use get post query hook and you can see
use get post query hook and you can see it has several different things here it
it has several different things here it has is loading is success is error and
has is loading is success is error and of course if we do have an error we want
of course if we do have an error we want to define that error so that means we're
to define that error so that means we're not going to need some of these other
not going to need some of these other things as well so let's go ahead and at
things as well so let's go ahead and at least remove the error that we know
least remove the error that we know we're not going to use and we'll see
we're not going to use and we'll see what else we're not using afterwards
what else we're not using afterwards this is going to change this just a
this is going to change this just a little bit because we're using new
little bit because we're using new indicators but we don't have to change
indicators but we don't have to change it a lot so instead of looking for post
it a lot so instead of looking for post status equals loading we're just looking
status equals loading we're just looking for
for is loading and then instead of post
is loading and then instead of post status succeeded we're just looking for
status succeeded we're just looking for is success
is success and then of course the else if post
and then of course the else if post status equals failed we're just looking
status equals failed we're just looking for is
for is error and now let's see if we need to
error and now let's see if we need to change anything else i'll hit ctrl b so
change anything else i'll hit ctrl b so we can see this full line but it pretty
we can see this full line but it pretty much will stay the same i believe so
much will stay the same i believe so there is our new content we're still
there is our new content we're still using the ordered post ids.map notice
using the ordered post ids.map notice that was up here above
that was up here above and that's because we're still using the
and that's because we're still using the selector select post ids that we already
selector select post ids that we already modified and made sure that the new
modified and made sure that the new state is being found inside of that
state is being found inside of that post slice file so it looks like we can
post slice file so it looks like we can get rid of this post status that we've
get rid of this post status that we've defined and if we come up here at the
defined and if we come up here at the top it looks like we can get rid of git
top it looks like we can get rid of git post status and get post error as well
post status and get post error as well from the imports and save now i would
from the imports and save now i would normally check our post list at this
normally check our post list at this time but we have changed so much about
time but we have changed so much about the post slice where our app will still
the post slice where our app will still be broken in many ways if we attempt to
be broken in many ways if we attempt to run it right now so let's go ahead and
run it right now so let's go ahead and keep making some changes i'll go back to
keep making some changes i'll go back to the file tree one thing that i do want
the file tree one thing that i do want to quickly change that really has
to quickly change that really has nothing to do with our rtk query
nothing to do with our rtk query normalized cache state or optimistic
normalized cache state or optimistic updates that we're applying today is the
updates that we're applying today is the post author component and i had just
post author component and i had just noticed really that we're not using a
noticed really that we're not using a link on the author's name so i'm going
link on the author's name so i'm going to go ahead and put in the link import
to go ahead and put in the link import link from react router dom and then
link from react router dom and then inside of the author where we're just
inside of the author where we're just displaying the author name inside of
displaying the author name inside of this tern area right here i'm just going
this tern area right here i'm just going to change this one line and maybe we can
to change this one line and maybe we can break it into separate lines so we can
break it into separate lines so we can see a little bit better but essentially
see a little bit better but essentially if true
if true we're going to return this link instead
we're going to return this link instead of just the author name so we're linking
of just the author name so we're linking to the author page other than that we're
to the author page other than that we're not changing anything else here in the
not changing anything else here in the post author and this will be in the
post author and this will be in the completed source code as well but if you
completed source code as well but if you want to quickly make the change it's
want to quickly make the change it's just link from react router dom and then
just link from react router dom and then it's providing the link
it's providing the link to that user page with the user id we
to that user page with the user id we already have the routing in place it's
already have the routing in place it's just something i hadn't previously added
just something i hadn't previously added okay let's go back to the post slice and
okay let's go back to the post slice and continue to add these methods so we can
continue to add these methods so we can eventually check our app and it won't be
eventually check our app and it won't be broken so we've got get posts right here
broken so we've got get posts right here but after get posts we have a comma
but after get posts we have a comma we're ready to put in our next method
we're ready to put in our next method i'll scroll up because it will take up
i'll scroll up because it will take up just as much room really
just as much room really paste this in and let's look at what
paste this in and let's look at what this is it's get posts by user id so
this is it's get posts by user id so it's going to be just a little different
it's going to be just a little different we now have a query that is receiving an
we now have a query that is receiving an argument so we set it up here with the
argument so we set it up here with the parameter definition of id
parameter definition of id and this is going to request posts and
and this is going to request posts and then it's going to have the user id
then it's going to have the user id attached to this request and so that
attached to this request and so that will give us the post just from a
will give us the post just from a specific user id we're using the
specific user id we're using the transform response
transform response just as we did above here so really the
just as we did above here so really the exact same concept because we still need
exact same concept because we still need to add this information to the posts if
to add this information to the posts if it doesn't exist and we're again using
it doesn't exist and we're again using postadapter.setall
postadapter.setall now this does not overwrite the cache
now this does not overwrite the cache state of the request for the full list
state of the request for the full list of posts because redux is subscribing to
of posts because redux is subscribing to these different queries which we'll be
these different queries which we'll be able to see when we complete if we use
able to see when we complete if we use redux dev tools because now this will
redux dev tools because now this will have a cache state for this specific
have a cache state for this specific query as well and again with the post
query as well and again with the post adapter we are normalizing this state so
adapter we are normalizing this state so it will also be normalized with an ids
it will also be normalized with an ids array and then having each post inside
array and then having each post inside of the entities object okay we'll scroll
of the entities object okay we'll scroll down here and look at provides tags
down here and look at provides tags now much like above we're not giving an
now much like above we're not giving an id of the full list but we are spreading
id of the full list but we are spreading the result that's ran through the map
the result that's ran through the map here and look we're using the ids array
here and look we're using the ids array and then we have the post and the id so
and then we have the post and the id so we could invalidate
we could invalidate this query for any one of these queries
this query for any one of these queries i guess any one of the users because we
i guess any one of the users because we would be looking at the individual posts
would be looking at the individual posts so if any one of those posts were
so if any one of those posts were invalidated in the future it could know
invalidated in the future it could know to invalidate this cache and re-run this
to invalidate this cache and re-run this query by auto fetching essentially and
query by auto fetching essentially and now remember each method that we add
now remember each method that we add above here so git post by user id
above here so git post by user id creates another custom hook so i'm just
creates another custom hook so i'm just going to select all of this and paste in
going to select all of this and paste in the change
the change what we've done is add the next custom
what we've done is add the next custom hook which is use get posts by user id
hook which is use get posts by user id that was the name we had so it starts
that was the name we had so it starts out with use and ends with query when
out with use and ends with query when this creates the custom hook and now
this creates the custom hook and now that we kind of know what we're doing
that we kind of know what we're doing here with the methods inside of this
here with the methods inside of this extended api slice let's just go ahead
extended api slice let's just go ahead and add the next method and now this
and add the next method and now this won't be a query this will be a mutation
won't be a query this will be a mutation so we have builder.mutation the previous
so we have builder.mutation the previous ones were queries because we were just
ones were queries because we were just querying data but now we're adding a new
querying data but now we're adding a new post so our other methods essentially
post so our other methods essentially updating deleting adding any of those
updating deleting adding any of those things will be mutations here we're
things will be mutations here we're passing in a post and i named this
passing in a post and i named this initial post because that's essentially
initial post because that's essentially what it is
what it is and we'll be posting to that slash post
and we'll be posting to that slash post url so the method is post
url so the method is post and then we're just adjusting a couple
and then we're just adjusting a couple of things here so we're actually
of things here so we're actually spreading in the post object and then
spreading in the post object and then we're overriding the user id making sure
we're overriding the user id making sure it's a number and not a string as we
it's a number and not a string as we post it we are adjusting the date and
post it we are adjusting the date and we're set in the reactions this is a new
we're set in the reactions this is a new post so all the reactions would be zero
post so all the reactions would be zero now a huge difference here from the
now a huge difference here from the queries as we perform a mutation we're
queries as we perform a mutation we're using
using invalidates tags instead of provides
invalidates tags instead of provides tags and this is going to invalidate the
tags and this is going to invalidate the list there's no individual post because
list there's no individual post because this post didn't already exist
this post didn't already exist but it would be part of the list so this
but it would be part of the list so this should invalidate the post list cache
should invalidate the post list cache okay scrolling up again for some more
okay scrolling up again for some more room and we'll put the next one which is
room and we'll put the next one which is the update so this update post is once
the update so this update post is once again a builder mutation once again
again a builder mutation once again receives that post object and notice now
receives that post object and notice now since this is an update i'm getting the
since this is an update i'm getting the id property from that initial post
id property from that initial post object this is a put method that we're
object this is a put method that we're using we're spreading in the original
using we're spreading in the original post and then we're going ahead and
post and then we're going ahead and updating the date everything else will
updating the date everything else will already exist because it was already a
already exist because it was already a pre-existing post so here we don't have
pre-existing post so here we don't have to worry about it actually having those
to worry about it actually having those other bits of data that we were adding
other bits of data that we were adding before here as we queried the data and
before here as we queried the data and then put it inside of our cache so now
then put it inside of our cache so now once we update we're just updating the
once we update we're just updating the state this is going to invalidate tags
state this is going to invalidate tags as well it's going to invalidate
as well it's going to invalidate whichever post id was there and so
whichever post id was there and so instead of just the result here we're
instead of just the result here we're using the argument because the argument
using the argument because the argument was that initial post so we're saying
was that initial post so we're saying argument.id just like we say
argument.id just like we say initialpost.id right here and finally
initialpost.id right here and finally let's go ahead and add the delete as
let's go ahead and add the delete as well so let's put the delete post right
well so let's put the delete post right here
here it's much the same now we're not getting
it's much the same now we're not getting the full post as the argument so this
the full post as the argument so this parameter just needs to be the id so
parameter just needs to be the id so what we can do is destructure the id
what we can do is destructure the id that we're getting from the post we
that we're getting from the post we don't need the rest of the post anywhere
don't need the rest of the post anywhere and then we're just passing that id here
and then we're just passing that id here to the url it's posts slash id so we
to the url it's posts slash id so we have that specific id
have that specific id and that's what we're deleting and of
and that's what we're deleting and of course here we're providing that id in
course here we're providing that id in the body of the request once again just
the body of the request once again just like the update it's the argument and so
like the update it's the argument and so the argument is going to be this object
the argument is going to be this object and we're not destructuring here so
and we're not destructuring here so we're saying argument dot id and with
we're saying argument dot id and with our methods all now in place we just
our methods all now in place we just need to update our exports here i'm
need to update our exports here i'm going to once again just select all of
going to once again just select all of these and paste over but you can see
these and paste over but you can see we've added the add new post mutation so
we've added the add new post mutation so because these are not queries they are
because these are not queries they are mutations they end in mutation they
mutations they end in mutation they still begin with the word use so we
still begin with the word use so we created add new post and the hook
created add new post and the hook created is use add new post mutation the
created is use add new post mutation the same for use update post mutation and
same for use update post mutation and use delete post mutation let's save
use delete post mutation let's save these changes and now we can move on to
these changes and now we can move on to the components so i'll go back to the
the components so i'll go back to the file tree and we're ready to make
file tree and we're ready to make changes to not the post list i went
changes to not the post list i went there by habit but we're going to change
there by habit but we're going to change the add post form component i'll press
the add post form component i'll press ctrl b to hide the file tree once again
ctrl b to hide the file tree once again and we're going to start out with an
and we're going to start out with an import and we need to import that
import and we need to import that mutation we created so this will be the
mutation we created so this will be the use add new post mutation that comes
use add new post mutation that comes from the post slice now we will no
from the post slice now we will no longer use dispatch so i'm just going to
longer use dispatch so i'm just going to highlight that and paste over it and
highlight that and paste over it and we'll bring in this add new post
we'll bring in this add new post function from our use add new post
function from our use add new post mutation notice i'm also bringing in an
mutation notice i'm also bringing in an is loading variable here and so we can
is loading variable here and so we can use that as well when we create our
use that as well when we create our content so we can use it conditionally
content so we can use it conditionally and now that we're doing that we're not
and now that we're doing that we're not going to bring in add new post from the
going to bring in add new post from the post slice that has been removed already
post slice that has been removed already and we're also not going to bring in use
and we're also not going to bring in use dispatch so i can get rid of that from
dispatch so i can get rid of that from the imports as well and now we can get
the imports as well and now we can get rid of our add request status we won't
rid of our add request status we won't be using that state anymore where we
be using that state anymore where we have use state set to idle so we can
have use state set to idle so we can remove that line of code and now i'll go
remove that line of code and now i'll go ahead and scroll down and we're going to
ahead and scroll down and we're going to be inside of our on save post click
be inside of our on save post click function what we won't do anymore is set
function what we won't do anymore is set the add request status we've removed
the add request status we've removed that state and we will no longer
that state and we will no longer dispatch add new post like we see here
dispatch add new post like we see here so i'm going to select both of these
so i'm going to select both of these and replace it with what we will now do
and replace it with what we will now do and this is a wait so we need to change
and this is a wait so we need to change our onsave post to async
our onsave post to async and now we're going to await our add new
and now we're going to await our add new post function that we're bringing in
post function that we're bringing in from our use add new post mutation
from our use add new post mutation and then we'll pass in the post so we'll
and then we'll pass in the post so we'll have the title the body with the content
have the title the body with the content that we're creating and then we'll have
that we're creating and then we'll have the user id here as well we'll still use
the user id here as well we'll still use unwrap because we're still in a try
unwrap because we're still in a try catch block but now we can also remove
catch block but now we can also remove this finally block from the try catch
this finally block from the try catch block because we're no longer using the
block because we're no longer using the add request status and one final change
add request status and one final change in our ad post form and that is going to
in our ad post form and that is going to be to replace the ad request status we
be to replace the ad request status we were checking here as we set the can
were checking here as we set the can save value that's now going to check
save value that's now going to check is loading and we want to make sure it
is loading and we want to make sure it is not loading and that's when can save
is not loading and that's when can save should work so let's go ahead and save
should work so let's go ahead and save and now back to the file tree we're
and now back to the file tree we're going to make changes that are nearly
going to make changes that are nearly identical to our edit post form but our
identical to our edit post form but our edit post form is going to be able to
edit post form is going to be able to update and delete so that makes a change
update and delete so that makes a change or two as well the first thing we'll do
or two as well the first thing we'll do is import our mutations and now we have
is import our mutations and now we have two mutations so you can see
two mutations so you can see where use or using use update post
where use or using use update post mutation and use delete post mutation
mutation and use delete post mutation i'll hide the file tree again with
i'll hide the file tree again with control b and once again inside the
control b and once again inside the component let's go ahead and use both of
component let's go ahead and use both of those so i'll paste that right here and
those so i'll paste that right here and we're bringing in the update post
we're bringing in the update post function and once again an is loading
function and once again an is loading status from the update and then we're
status from the update and then we're bringing in a delete post function from
bringing in a delete post function from that use delete post mutation hook as
that use delete post mutation hook as well
well after that we will not need the dispatch
after that we will not need the dispatch so we can remove that and once again we
so we can remove that and once again we will not need the request status or set
will not need the request status or set request data state so we can remove that
request data state so we can remove that too
too and it looks like i've got an extra line
and it looks like i've got an extra line i'll remove now i'll go ahead and scroll
i'll remove now i'll go ahead and scroll up and we should be changing some of the
up and we should be changing some of the same things here as well so on can save
same things here as well so on can save once again we are going to change that
once again we are going to change that request status idle that we're no longer
request status idle that we're no longer using state for to just making sure that
using state for to just making sure that is loading is not true now i'll scroll
is loading is not true now i'll scroll up a little more we need to change our
up a little more we need to change our onsave post click here to an async
onsave post click here to an async function
function we'll once again remove the set request
we'll once again remove the set request status and the dispatch and i'll replace
status and the dispatch and i'll replace that with an await update post and here
that with an await update post and here we pass in the post once again that is
we pass in the post once again that is being created and once again we use
being created and once again we use unwrap because we're inside of a try
unwrap because we're inside of a try catch block now we can remove the
catch block now we can remove the finally block from the try catch block
finally block from the try catch block as well but we're not quite finished
as well but we're not quite finished because that's just saving the update so
because that's just saving the update so we need to scroll down because we also
we need to scroll down because we also have on delete post clicked which will
have on delete post clicked which will also make an async function we'll remove
also make an async function we'll remove the set request status and the dispatch
the set request status and the dispatch here as well
here as well and in this place we'll put the await
and in this place we'll put the await delete post and here we just pass in the
delete post and here we just pass in the post id because if you remember that's
post id because if you remember that's all that's needed back in our extended
all that's needed back in our extended api slice we're using unwrap here as
api slice we're using unwrap here as well because it's in the try catch block
well because it's in the try catch block and we can remove the finally as well
and we can remove the finally as well now there's one more big component
now there's one more big component change we need to make so we'll go back
change we need to make so we'll go back to the file tree but this is not in the
to the file tree but this is not in the post folder at all it's actually in the
post folder at all it's actually in the users folder and it's going to be on the
users folder and it's going to be on the user page remember we're getting posts
user page remember we're getting posts by the user id so we can display them of
by the user id so we can display them of course on the user page so that's what
course on the user page so that's what we're going to do here let's go ahead
we're going to do here let's go ahead and add the import we need and that's
and add the import we need and that's going to be use get posts by user id
going to be use get posts by user id query so we're coming up out of the
query so we're coming up out of the users folder into the post folder and
users folder into the post folder and grabbing that post slice where that new
grabbing that post slice where that new custom hook is created by rtk query i'm
custom hook is created by rtk query i'm going to hide the file tree once again
going to hide the file tree once again we will not need this import with select
we will not need this import with select all posts or select posts by user so we
all posts or select posts by user so we can go ahead and remove that import and
can go ahead and remove that import and below we'll bring in our hook right
below we'll bring in our hook right where we define posts for user so let's
where we define posts for user so let's just paste over that and now you can see
just paste over that and now you can see with the get post by user id query and
with the get post by user id query and we're passing in the user id that we get
we're passing in the user id that we get from use params with react router
from use params with react router so once we have that we're defining the
so once we have that we're defining the data we get from this hook as posts for
data we get from this hook as posts for user so it can replace what we were
user so it can replace what we were doing and now we have that same status
doing and now we have that same status that we did before so we can
that we did before so we can conditionally render our components so
conditionally render our components so we have is loading is success is error
we have is loading is success is error and then of course error if there is an
and then of course error if there is an error and now our content is going to
error and now our content is going to change somewhat so what i'm going to do
change somewhat so what i'm going to do is just select the post titles and paste
is just select the post titles and paste over it's where we create our content
over it's where we create our content and we're actually going to call it
and we're actually going to call it content so while i'm thinking of it i'll
content so while i'm thinking of it i'll come down here in the jsx and just paste
come down here in the jsx and just paste our content in here instead where we
our content in here instead where we have post titles so we'll just change
have post titles so we'll just change that to content okay to break this down
that to content okay to break this down up above we're defining content and then
up above we're defining content and then we're checking those different
we're checking those different progresses so we have is loading so if
progresses so we have is loading so if that's true we're just going to change
that's true we're just going to change the content to a loading status then we
the content to a loading status then we have is success and this is where it
have is success and this is where it gets a little more complicated because
gets a little more complicated because remember we now have normalized state so
remember we now have normalized state so our post for users the data that we
our post for users the data that we receive has that ids array and then it
receive has that ids array and then it has the entities object that has all of
has the entities object that has all of the individual posts for the user so
the individual posts for the user so we're destructuring that right here and
we're destructuring that right here and we're mapping over the ids array now for
we're mapping over the ids array now for each id we can create a list item and
each id we can create a list item and we're going to link to the post but then
we're going to link to the post but then when we get to the content here and we
when we get to the content here and we need the title we have to use that
need the title we have to use that entities object as a lookup object so we
entities object as a lookup object so we pass in the id and that gives us the
pass in the id and that gives us the specific post it's an object lookup
specific post it's an object lookup and then we can reference the title and
and then we can reference the title and then our final of course is if is error
then our final of course is if is error is true then we display the error and
is true then we display the error and that's all the changes we need to make
that's all the changes we need to make well at least that's all the changes we
well at least that's all the changes we need to make for this component let's go
need to make for this component let's go ahead and move back to the file tree
ahead and move back to the file tree because we have just a couple of more
because we have just a couple of more changes to make before everything is
changes to make before everything is going to work in our application
going to work in our application one area we need to fix and this is just
one area we need to fix and this is just left over from the previous tutorial is
left over from the previous tutorial is the header js because we're going ahead
the header js because we're going ahead and importing in increased count and git
and importing in increased count and git count when we just displayed something
count when we just displayed something in that tutorial about count and we
in that tutorial about count and we don't really need it here and of course
don't really need it here and of course the dispatch and setting count here as
the dispatch and setting count here as well we're not going to use any of that
well we're not going to use any of that so let's go ahead and remove those let's
so let's go ahead and remove those let's remove the button that had the count
remove the button that had the count because it's really not a feature we
because it's really not a feature we need in our blog that we're going to use
need in our blog that we're going to use and that means we don't need the imports
and that means we don't need the imports of use dispatch and use selector so if
of use dispatch and use selector so if you have that in your starter code you
you have that in your starter code you can remove everything to do with the
can remove everything to do with the count outside or inside of the header
count outside or inside of the header component so we just removed all of that
component so we just removed all of that and now the last thing we really need to
and now the last thing we really need to do is move on to the reactions and that
do is move on to the reactions and that is inside of the posts directory here
is inside of the posts directory here inside of features and we'll go to the
inside of features and we'll go to the reaction buttons js but we're also going
reaction buttons js but we're also going to have to go back to that post slice
to have to go back to that post slice where our extended api slice is and make
where our extended api slice is and make one more method here inside of the
one more method here inside of the extended api slice now this is a larger
extended api slice now this is a larger method that i'm going to put in here so
method that i'm going to put in here so we'll definitely break it down after i
we'll definitely break it down after i paste it in
paste it in and here it is so we'll scroll up here
and here it is so we'll scroll up here we've got add reaction it is once again
we've got add reaction it is once again a builder mutation but we don't want to
a builder mutation but we don't want to reload our list every time we add a
reload our list every time we add a reaction so we're going to do this
reaction so we're going to do this differently and this is what is called
differently and this is what is called an optimistic update and that's what
an optimistic update and that's what we're going to perform here so i'll
we're going to perform here so i'll press ctrl d to hide the file tree again
press ctrl d to hide the file tree again and let's break this all down first we
and let's break this all down first we have a query and this query is going to
have a query and this query is going to receive a post id
receive a post id and the reactions notice we're
and the reactions notice we're destructuring those from the object
destructuring those from the object being sent in okay then we have the url
being sent in okay then we have the url that's just going to posts with the post
that's just going to posts with the post id the method is going to be patch now
id the method is going to be patch now notice this note right here and this
notice this note right here and this comes directly from the docs example as
comes directly from the docs example as well and they're absolutely right it
well and they're absolutely right it says in a real app we'd probably need to
says in a real app we'd probably need to base this on the user id somehow so a
base this on the user id somehow so a user can't do the same reaction more
user can't do the same reaction more than once and that is true with this
than once and that is true with this current setup a user will be able to
current setup a user will be able to have a reaction more than once what
have a reaction more than once what we're doing differently from the docs
we're doing differently from the docs example is they were just passing in the
example is they were just passing in the individual reaction and incrementing it
individual reaction and incrementing it because they didn't give this example
because they didn't give this example with normalized state i'm passing in all
with normalized state i'm passing in all of the reactions for the post and then
of the reactions for the post and then we're going to replace the existing
we're going to replace the existing reactions with the reactions that are
reactions with the reactions that are passed in
passed in okay once we have that and that would
okay once we have that and that would typically be what we would do but now
typically be what we would do but now notice we have an on query started
notice we have an on query started handler now this is a little different
handler now this is a little different we're once again passing the post id and
we're once again passing the post id and the reactions just like we did above
the reactions just like we did above with the query but then it has a second
with the query but then it has a second parameter as well
parameter as well that parameter has some things in there
that parameter has some things in there we can use one is dispatch and another
we can use one is dispatch and another is query fulfilled which is a promise
is query fulfilled which is a promise and so we're going to look at that to
and so we're going to look at that to know some status as well now our note
know some status as well now our note update query data it says it requires
update query data it says it requires the endpoint name and cache key
the endpoint name and cache key arguments so it knows which piece of
arguments so it knows which piece of cache state to update well that's what
cache state to update well that's what we're going to do right down here so
we're going to do right down here so we're defining patch result then we're
we're defining patch result then we're using dispatch that we got from the
using dispatch that we got from the second parameter up here of on the on
second parameter up here of on the on query started handler and what we're
query started handler and what we're going to dispatch is extended api dot
going to dispatch is extended api dot util which we hadn't seen before and
util which we hadn't seen before and then we can get this update query data
then we can get this update query data and there is where we pass in the
and there is where we pass in the endpoint now we have undefined here for
endpoint now we have undefined here for that cache key argument i believe but we
that cache key argument i believe but we do have the end point and that's all we
do have the end point and that's all we really need but the draft is a draft of
really need but the draft is a draft of our data so this is immer wrapped so
our data so this is immer wrapped so we're once again using immer js like we
we're once again using immer js like we did inside of create slice and
did inside of create slice and the data here can be mutated because
the data here can be mutated because then emerge a s will handle it correctly
then emerge a s will handle it correctly for us so what i'm going to do is define
for us so what i'm going to do is define the post
the post and set it equal to draft dot entities
and set it equal to draft dot entities remember this is a draft of our data and
remember this is a draft of our data and our data has the ids array and the
our data has the ids array and the entities object and i'll pass in that
entities object and i'll pass in that post id so this is an object lookup
post id so this is an object lookup again so i'm getting that specific post
again so i'm getting that specific post and then if that post exists i'm set in
and then if that post exists i'm set in the reactions to the reactions that we
the reactions to the reactions that we passed in to this builder mutation and
passed in to this builder mutation and so that would normally be a mutation
so that would normally be a mutation here but emerge a s is going to handle
here but emerge a s is going to handle that correctly for us now after we do
that correctly for us now after we do all of that
all of that what happens is we await for that
what happens is we await for that promise to fulfill the promise that was
promise to fulfill the promise that was in the parameter here so query fulfilled
in the parameter here so query fulfilled otherwise we're going to undo this patch
otherwise we're going to undo this patch and that's if it catches an error there
and that's if it catches an error there it will undo it and that is because this
it will undo it and that is because this is an optimistic update so what we're
is an optimistic update so what we're really doing inside of this patch result
really doing inside of this patch result here
here is updating
is updating our cache
our cache and that is happening
and that is happening optimistically
optimistically possibly before the data at the api has
possibly before the data at the api has been updated so we're instantly seeing
been updated so we're instantly seeing that in our
that in our ui what happens is we click on the
ui what happens is we click on the reaction and it instantly updates and
reaction and it instantly updates and then you see the network request go to
then you see the network request go to the api to go ahead and update that data
the api to go ahead and update that data so it will match what we already see in
so it will match what we already see in our ui but if it fails for any reason
our ui but if it fails for any reason then it will undo what we have changed
then it will undo what we have changed inside of our cache our data as well so
inside of our cache our data as well so that is why we look for query fulfilled
that is why we look for query fulfilled and we hope it fulfills but if for some
and we hope it fulfills but if for some reason it doesn't just because we've
reason it doesn't just because we've optimistically updated doesn't mean that
optimistically updated doesn't mean that it cannot be undone
it cannot be undone so that's how that works an optimistic
so that's how that works an optimistic update and i know it's a little bit more
update and i know it's a little bit more complicated than just sending and
complicated than just sending and receiving data from the api and of
receiving data from the api and of course updating our state with that as
course updating our state with that as well but we're optimistically
well but we're optimistically updating our cache possibly before the
updating our cache possibly before the data is received at the api with this
data is received at the api with this setup and then a final note on this add
setup and then a final note on this add reaction notice we're not using
reaction notice we're not using invalidates tags anywhere with this and
invalidates tags anywhere with this and that is because we don't want to
that is because we don't want to re-fetch the list every time a reaction
re-fetch the list every time a reaction is added so we're not going to
is added so we're not going to invalidate any post or list what we're
invalidate any post or list what we're going to do is optimistically update the
going to do is optimistically update the cache already and not have to do another
cache already and not have to do another request but we are going to update the
request but we are going to update the data at the api as well okay let's save
data at the api as well okay let's save these changes and now let's move to the
these changes and now let's move to the add reaction or i'm sorry the reaction
add reaction or i'm sorry the reaction buttons component and what we're going
buttons component and what we're going to do is add reaction so we can remove
to do is add reaction so we can remove this import use dispatch and import
this import use dispatch and import reaction added from the post slice we'll
reaction added from the post slice we'll no longer need those what we will import
no longer need those what we will import is the use add reaction mutation from
is the use add reaction mutation from the post slice now let's go ahead and
the post slice now let's go ahead and remove dispatch from the component
remove dispatch from the component itself and we'll replace that with
itself and we'll replace that with calling our use add reaction mutation
calling our use add reaction mutation hook and getting the add reaction
hook and getting the add reaction function from it now i'm going to scroll
function from it now i'm going to scroll up and we're just going to change a
up and we're just going to change a little bit about our button we will
little bit about our button we will still use object dot entries and we'll
still use object dot entries and we'll still use the reaction emoji here and
still use the reaction emoji here and map over it with the name and the emoji
map over it with the name and the emoji no changes there the button will still
no changes there the button will still have a key that's the name type button
have a key that's the name type button class name reaction button but our on
class name reaction button but our on click will definitely change so let's go
click will definitely change so let's go ahead and replace the on click
ahead and replace the on click and you can see what we're doing now is
and you can see what we're doing now is defining a new value and we're getting
defining a new value and we're getting the post.reactions name and adding one
the post.reactions name and adding one to it so that's the new value then when
to it so that's the new value then when we add reaction we're passing in all of
we add reaction we're passing in all of the reactions so we've got the post id
the reactions so we've got the post id that we need that's passed in and then
that we need that's passed in and then the reactions here so we spread in the
the reactions here so we spread in the post reactions and then we overwrite the
post reactions and then we overwrite the current reaction that with that new
current reaction that with that new value and so now it will have the
value and so now it will have the increment for that one reaction then
increment for that one reaction then down here everything should still be the
down here everything should still be the same we've got emoji post dot reactions
same we've got emoji post dot reactions and the name that shows
and the name that shows and our jsx just shows the reaction
and our jsx just shows the reaction buttons so that's all good we can save
buttons so that's all good we can save those changes i think we're just about
those changes i think we're just about ready to try out our application let's
ready to try out our application let's go back to the post slice i'm thinking
go back to the post slice i'm thinking after i discussed this add reaction
after i discussed this add reaction which is the builder mutation that's
which is the builder mutation that's fairly large we didn't go ahead and add
fairly large we didn't go ahead and add it to our export here of the different
it to our export here of the different custom hooks so let's do that as well
custom hooks so let's do that as well this would be use add reaction mutation
this would be use add reaction mutation so now let's save that okay let's open
so now let's save that okay let's open up a command line remember we have got
up a command line remember we have got our json server running at the other
our json server running at the other command line so we open up a second one
command line so we open up a second one now and here i'm going to type npm
now and here i'm going to type npm start
start and this should fire up our blog so
and this should fire up our blog so let's see what we get for our blog in
let's see what we get for our blog in the web page it was loading and now we
the web page it was loading and now we have our blog it looks like everything's
have our blog it looks like everything's good see if we can view a post
good see if we can view a post we're viewing the post
we're viewing the post we can view the author page and see
we can view the author page and see other posts from that author so that all
other posts from that author so that all looks good let's see a list of users
looks good let's see a list of users that's good and remember we have not
that's good and remember we have not changed our users over from the async
changed our users over from the async thunk and the user slice that we created
thunk and the user slice that we created before that's going to be your
before that's going to be your assignment at the end of this tutorial
assignment at the end of this tutorial then you can look at my completed code
then you can look at my completed code on github to match that up but while we
on github to match that up but while we have this open let's go ahead and see if
have this open let's go ahead and see if we can add some reactions and they
we can add some reactions and they increment quickly that's great so
increment quickly that's great so everything is working as we expect now
everything is working as we expect now let's go ahead and look here at this
let's go ahead and look here at this in dev tools this application in dev
in dev tools this application in dev tools and we'll open up redux here so
tools and we'll open up redux here so now we can check some of our state
now we can check some of our state and see what's being used in the state i
and see what's being used in the state i wish i had just a little bit more room
wish i had just a little bit more room but overall we have the api and we have
but overall we have the api and we have users
users in the state so let's look at the api
in the state so let's look at the api and then it has queries and if we open
and then it has queries and if we open up the queries you can see git posts has
up the queries you can see git posts has been used and then we used get post by
been used and then we used get post by user id
user id and then they both keep their own
and then they both keep their own information so then we'll have data
information so then we'll have data from that get posts and inside here we
from that get posts and inside here we see the data has the ids array and the
see the data has the ids array and the entities if we look at the ids array
entities if we look at the ids array it's just an array of id numbers
it's just an array of id numbers and then the entities
and then the entities is an array or not an array actually
is an array or not an array actually it's an object but it has the
it's an object but it has the number 2 and then the object assigned to
number 2 and then the object assigned to it so if we drop that down then you see
it so if we drop that down then you see id2 title you'll see the full post
id2 title you'll see the full post entity has each one but it's also an
entity has each one but it's also an object with a number as it goes so
object with a number as it goes so that's why we can use it as an object
that's why we can use it as an object lookup with the ids and then any changes
lookup with the ids and then any changes we make we can look at the differences
we make we can look at the differences and you can also see what the state is
and you can also see what the state is subscribed to
subscribed to or the different actions so redux dev
or the different actions so redux dev tools linked to in the description is
tools linked to in the description is very very useful as well but now let's
very very useful as well but now let's go to the network tab
go to the network tab and see what we get here when we make
and see what we get here when we make different requests right now we'll
different requests right now we'll request the home page there's no more
request the home page there's no more network request there because we've
network request there because we've already got those post lists so now
already got those post lists so now let's go ahead
let's go ahead and go to leanne graham's page and
and go to leanne graham's page and notice then we had a user id equal one
notice then we had a user id equal one request and that was a fetch so we got
request and that was a fetch so we got that data and we can look at an
that data and we can look at an individual post if we go back to
individual post if we go back to leanne's page
leanne's page no other network request it didn't
no other network request it didn't happen again because it gets it from the
happen again because it gets it from the cache now if we go to users and request
cache now if we go to users and request another user id
another user id then we see that user id equal to 10 and
then we see that user id equal to 10 and now that is also cached so now we have
now that is also cached so now we have two cached queries there for users we
two cached queries there for users we can look at an individual post there but
can look at an individual post there but if we go back to that user we don't see
if we go back to that user we don't see another request if we go back to users
another request if we go back to users here go back to leanne graham
here go back to leanne graham we don't see another request because we
we don't see another request because we already have that data here now it will
already have that data here now it will eventually expire
eventually expire and redux handles that for us as well
and redux handles that for us as well remember that middleware handles those
remember that middleware handles those expirations so you can see how efficient
expirations so you can see how efficient this would be now if we change something
this would be now if we change something say we update a post so let's view the
say we update a post so let's view the post
post then let's choose edit post and here
then let's choose edit post and here i'll just change the text of the post to
i'll just change the text of the post to testing
testing and then i'll save that
and then i'll save that now you can see several things happened
now you can see several things happened we had a pre-flight request here with
we had a pre-flight request here with this post and then there was the fetch
this post and then there was the fetch and you can see it was actually a put
and you can see it was actually a put request that was sent and we got 200 for
request that was sent and we got 200 for that
that and then that caused the posts to
and then that caused the posts to invalidate the cash so the posts were
invalidate the cash so the posts were once again
once again fetched at that point so there you can
fetched at that point so there you can see how everything is working and you
see how everything is working and you can play around with that in redux dev
can play around with that in redux dev tools and also look at the network tab
tools and also look at the network tab but it's all working as expected
but it's all working as expected congratulations if you followed me all
congratulations if you followed me all the way through to the end of this
the way through to the end of this project you now have a fully functioning
project you now have a fully functioning blog that has integrated normalized
blog that has integrated normalized cache state and it has some optimistic
cache state and it has some optimistic updates which is something else we
updates which is something else we didn't do there but we can go ahead and
didn't do there but we can go ahead and do the reactions i guess open the
do the reactions i guess open the console back up now we should see
console back up now we should see a network request for every reaction and
a network request for every reaction and there we see that so if i do it again
there we see that so if i do it again we'll continue to see that one was a
we'll continue to see that one was a pre-flight request but the others were
pre-flight request but the others were fetch
fetch and we're doing the optimistic updates
and we're doing the optimistic updates so notice it updates here immediately
so notice it updates here immediately and then we see the request so overall
and then we see the request so overall we've implemented a lot of things here
we've implemented a lot of things here with redux toolkit and rtk query we've
with redux toolkit and rtk query we've got react going normalized state
got react going normalized state optimistic updates congratulations on
optimistic updates congratulations on making it to the end of this i hope it's
making it to the end of this i hope it's given you a good start with redux
given you a good start with redux toolkit remember to keep striving for
toolkit remember to keep striving for progress over perfection and a little
progress over perfection and a little progress every day will go a very long
progress every day will go a very long way
way please give this video a like if it's
please give this video a like if it's helped you and thank you for watching
helped you and thank you for watching and subscribing you're helping my
and subscribing you're helping my channel grow have a great day and let's
channel grow have a great day and let's write more code together very soon
Click on any text or timestamp to jump to that moment in the video
Share:
Most transcripts ready in under 5 seconds
One-Click Copy125+ LanguagesSearch ContentJump to Timestamps
Paste YouTube URL
Enter any YouTube video link to get the full transcript
Transcript Extraction Form
Most transcripts ready in under 5 seconds
Get Our Chrome Extension
Get transcripts instantly without leaving YouTube. Install our Chrome extension for one-click access to any video's transcript directly on the watch page.