In this intermediate react course about React
state management, Jack Harrington will teach you about hooks state context, using request
libraries for state management, Redux, and more. Hi, I'm Jack Harrington. I'm a principal
full stack software engineer. And I am super excited to be here on Free Code Camp,
talking about my favorite topic, which is react state management. And the first thing I
want to answer about React state management is, what is state management. So state management
is basically half of your React app. When you think about it, you've got the presentation
side of the house, that's the HTML and how you format it. And then there is the data
that's in your application, the state, and to me state in state management is the beating
heart of a React app. And why do I say that? Well, it actually is, the only time a React app will
rerender is when state changes when you add an item to a cart, when you remove an item from
a cart. That's the time when the React app re renders. And so state is the engine that moves
your React app. In fact, I would go so far as to say that reacts whole job is to turn state
into HTML, at least in the web context. So in this video, I'm going to give you a complete
overview of all of the different ways that you can manage state in your React application. And
that's going to start off with React Native state management. This is the hooks we've all come to
know and love things like use state use reducer, use memo and use the fact we are going to drill in
deep on these hooks and make sure that we really understand them because they are the foundation
upon which all of the other state management models are built. In the second section, we're
going to talk about indirect state managers. These are third party libraries like React, query,
react location, React Router, it's not their primary job to manage state, but react query,
for example, it goes off and agrees data from the server and it gets it back. And now it holds
that data which has an effect managing that state. And perhaps the combination of native hooks,
and one of these third party libraries, like React query or application is enough for your
state management needs for your application. And then in the third section of the video, we're
gonna talk about direct state managers. These are third party libraries whose sole function is to
manage state, things like Redux, Joe tie vow, sheEO and zouche done, and we'll talk about the
different models and which one you might want to select for your application. And then, at the end,
we'll talk about some new things that are coming with some react RFCs that are just coming out
next Jas 13. That changed the way that we think about how we might want to manage state in our
application. And I'll sum up by giving you some recommendations about what I suggest you might
think about in terms of choosing state management technologies for your app. But it all starts with
getting to know react hooks really well. So let's get right into it. So we're going to start off by
taking a look at native state management in React, and in particular, concentrating on the use
state hook. So to do that, I'm going to build a VT application, I'll do that using yarn, create
Veet then either the name of the application that you want, so I'm going to going to use native use
date. And now V which is a awesome way to create web applications can take multiple templates,
I'm going to use the template for React. Alright, now I'm gonna bring that up in VS code. Alright, so here we have our
application and bring up the console. And then we'll do yarn to install all the
dependencies. And then yarn dev to start it up. And I'll click on this link. And there you go.
Awesome. Here's our application. It's even got a little bit of interactivity, a little state in
this case, but we're just gonna remove everything that we see here to start. So where is that
located? Let's locate it over map dot JSX. And I'm going to remove pretty much all of this. But we'll keep around Eustache because we know
we're gonna need it. Okay, so the first thing we're gonna do is experiment with using a numeric
state a number. And actually a counter is the best way to do that. So we're going to basically
we implement this from scratch. Now all of this code is available to you on GitHub for free
in the link in the description down below. But you can just follow along me if you please. So
okay, so here's our end. We're gonna it define that we have some state associated with this
component. So to do that we say use state. And we'll start our counter off at a
given number, say let's start with 10. Now the output of use eight is an array. So let's
go and get data array. And within that array, the first item is the current value of that
piece of state. So we'll call that count. And then the second item is a setter
function, you call that function to set that piece of state. So call that set count.
Now let's create a button that has the count. And let's take a look see what it looks like.
All right, so we've got a button down here, kind of hard to see a little bit. But it's got
10 on it, but it doesn't do anything yet. So we want to create an onclick. So how do we do
that? Well use unclick. And then we give it a function. So we're gonna say add one is our
function. And then we'll define that function. So here's a mistake that I've seen people
do. See, we will do count plus plus, I think the idea is that well, count is just
a count. And when I said it, it should be retained. So let's try that out. Let's see if that
actually works. But click on that nothing happens. And so why is that? Well, we're seeing that we're
getting an assignment to a constant variable. Now, what's outputting? That is actually console ninja,
you want to go grab that? That's my folks that Wallaby link to that also in the description down
below. It's free. And it's super handy like this. So well, okay, we get it. This is defined as a
const. Right? So let's go and redefine that as a let, and maybe that will work. All right, let's
give it a try. Now, click still doesn't work, but we don't get an error. Interesting. Okay.
So why is this? Well, learning why this is, is really critical to understanding pretty much
all of state management in React. So I want to spend a bit of time on it. And one of the things
I want to do is I want to use a workbook to show how this is actually working. So I'm going to
create in as another extension called cuaca, a worksheet. And what we'll do is I'm going
to create a function that returns a value kind of like use date, so we'll
call that function get state. And let's say that it has some value and say 42. And then when he called get
state, or just returns that value, now down here, I'm gonna call get state.
Now currently just returns 42. But I'm gonna go store that somewhere. So I need to
store that in a new value, so like my value. And we'll just ask cuaca, what my value is.
It's 42. And now if I set it to something else, now my value is 22. Cool. But what happens when
I go and get the state again, so I'll say my value again. And now my value again, is still 42.
Because setting the value of a return, just sets your local copy. So scalars, and that includes
strings, numbers, and booleans. So a number in this case, are returned and passed by value, where
arrays and objects are passed and returned by reference. And there's a huge difference there.
So when you're returning something by value, you don't get it, you get a copy of it, which
is not the same thing. Now you could say, Oh, Jack, you know, you got it all wrong. And
this is returning an array. Okay, fine. Go try the same thing with array. All right,
yeah. So we see that, again, my values 42, we set the local copy to 22. And then we again,
set that and there's no difference, same sort of thing down here. Right, all we're doing is
just d structuring a scalar within an array. Now there actually is a way to kind of make
get state do this. And that's the beauty of JavaScript enclosures. But when you hack around
that much, you're not actually representing how React is actually managing state. And the proof is
in the pudding. The proof is in this doesn't work. So what works is to use that set count function
that's given to us to set that count to be the count plus one, or whatever you So let's go over
here and try it again. And now it works perfectly. So now I mentioned that count is associated with
this particular instance of this component. But this component is the app, right? So we
only have one. So what if we're going to have multiple ones of these, let's go and
take an app and just rename it counter. And then we'll make a new app, then we'll just
make a bunch of counters and see how that works. Now we have one counter down here. Let's go make
a bunch. Cool. Now we've got four count buttons. And now we can click on each one of them. And
they all independently set. And that's what I mean by the state being coupled with the instance
of that component, each one of these components, these counter components, maintains its own
count. And thus, going back over here, we can go in independently, you take each one of these, and
they all maintain their states individually. So we talked about how to manage a scalar, a simple
scalar using use eight. Let's talk about how to manage an array. So we do that a lot as well. So
I'm going to create an array of names. And then we're going to have an ability to add a name to
that. So let's get rid of one of these counters. And I'll create a new function, which
is a component called name list. So let's create some state
to hold that list of names. Jack, Jill and John. In fact, actually,
let's go fix this to be const. Again, so that's good, okay, good. And now
we're going to render that state. Nice, and let's go and
actually put it into our app. All right, good looking list there. Alright,
so we want to be able to add an item to that array. So we need an input field.
So that's another thing you can do, you can have multiple pieces of state
associated with the same component. So we're just going to have another, here's a
state called name, which is a scalar string. And then we need an input field. Now when this text changes, we get an event. And
that event has a value for the current target the target of that event being that input. And within
that target, we have the current value, that would be the last thing that the user typed or the last
state of the text field. So we just set the name to that target value. And again, we're using the
setter, right, we don't want to go and say name equals target value, because we know for strings,
and for numbers and Booleans, we get back copies, we don't get back the real thing. So we can't
just set it, we got to use that setter set name. So now we've got our set. Let's go take a look.
And see that works. seems to work pretty well. Cool. So now let's go and add a button so we can
add an item to the list. Now we need to add a click handler that is going to respond to clicking
on Add name to add that name to that list. Okay, so here we have ADD name. So how
are we going to implement on this? Well, what we could do is good just
a push the name on to list. Alright, let's go check this out. I'm gonna go
and add some just random text in there. I'll hit Add name, and nothing happens. But here's
an interesting deal. If I change the state of the component, we'll get a rerender. So
if I backspace, that's going to change the state of the Name field, which calls
set name, set name then does two things. It sets the name. And it also in queues a
rerender request for this particular component. When the rerender happens, we get that same list.
And then we print it out. Now that's the big difference here between scalars and references.
So strings, numbers, and billions are scalars. You get back the value, a copy of the value
and then that's it, you got the local copy. But when it comes to objects and arrays, JavaScript
manages those by reference. And when you give react a reference to this particular array, it
then holds not the array data. It's setup, but it holds a reference to that array. And then
it gives us back that same array reference, we then use an in place command push to mutate
that data of that array in place. And that's why as we add more items, when we do a
refresh, we actually get that updated data. The problem is that react has no idea that
we've done that. So the second part of what a setter does, which is to in queue, a
request for a rerender of a component doesn't happen. So what if we did
this? What if we said setlist? And we'll just give it the same list again, I
mean, hey, you know, we've made a change, which is just going rerender. Okay, let's try that. So
fresh, add the name again, and nothing happens. So here's the deal. When I call any
setter, when it comes to use date, it looks at the old value, and it looks at the new
value. And if the old value and new value are the same, it just says I don't care. Thanks. But you
know, you're not really doing anything. So what we're doing in this case is where we are giving it
back exactly the same reference as we had before. So it's looking at those two references and
saying, oh, that's the same array. And so you're just asking me to do nothing really. And so it
doesn't in-q A rerender request. So we need to do in order to make this work is instead of in place,
mutating the array, we create a new array that has the contents of the old array, plus the new name.
So maybe we do that as we create a new array. We'll give it all of the old
array, so list in this case, and then we give it our new name. Now we
don't have to do that push anymore. Hit save. And away we go. Even better, we can do
set name and set that to an empty string. Then after we add it, that's set to an empty
string. And it's important to know that with React 17 with React 18. These setters are
batched. So you do setlist it says that value in queues a request, set name runs, right
after that sets that name again and queues a request to rerender. The component. React says
hey, I've already got one for this component, and it just ignores it. And then when the rerender
comes round, both of those values have been set. Now the last thing I want to cover about
use state before we move on to use reducer is that you state also can take a function
as a starting point. So let's just take our example here of a single simple string,
and then we'll give it a function. And that function will return
a string and says, Jack. And there you go now is initialized
jack. So the value of doing it this way, is that if you've got some sort of
complex calculation that you need, in the creation of this use state, you can
do it all within that function. And that function will guaranteed only ever get run
once, when that component is first created. Let's continue to take a look at native state
management in react by taking a look at use reducer, which is another way to store state in
connection with a component just like you state. Alright, let's go and create another example
application. We'll call this one native use reducer. And again, this is available to you in
the GitHub repository associated with this video. And I'll bring it up in VS code. Let's install it and then run it and bring
it up in the browser. Okay, it looks good. So let's pare this down again. Okay, we're all cleaned up. But before we get into
use reducer, I do want to talk a little bit about a reducer function in general. And a good way to
do that would be to open up a TypeScript workbook and look at the reduce method on an array.
So let's give ourselves an array of numbers. And we want to total up those numbers.
So let's start with the total. And then we'll iterate through all the numbers and
then add that to the total. And eventually, well, what do we get? We get 6010 plus 20 plus 3060.
Think that makes sense. All right. So Another way to do that is to use a reducer function.
So numbers has a function called reduce. And that reduce function takes two
parameters, it takes a reducer function, which returns something, and then it takes an
initial value. So our initial value here would be the same as this total would start off at
zero. So that's easy enough. So this reducer function takes two parameters, it takes the
current value, which would be zero to start. And then it takes the number at the given index
as it indexes through the entire array. So starts out with 2010 20, and 30. So we'll call that
N. And the output of a reducer is the new value for the next iteration. So in this case, we want
to take the existing value, so starting at zero, and then add on each number as we go through.
Now, if we look at this, we get 60 as the output, how cool is that? So this function right here,
that we pass to reuse is called the reducer. And it takes two parameters, it takes the current
value, and then it takes some new value. And in the case of numbers, because we're iterating
through an array, it takes each one of the numbers as we go through. And then the output of a
reducer is what the next iterations input will be. So this reducer pattern is going to show up in two
places. In this video, it's going to show up in the user reducer example that we're going to build
here. And it's also going to show up in Redux. So learning how reducer is work is beneficial across
state management. Okay, so what do we want to do with use reducer here? Well, we want to rebuild
this example of a list of names and then an input name, and build it all in one piece of state
management. And so we'll bring in user reducer. And we'll invoke it. And the first thing that's
designed on is what's going to be in the state, so the state is going to have a list
of names start off with an empty array, and then it's going to have the current
name, which will just be an empty string. And that is going to be the state. So use
reducer, just like use state returns an array, that array has two elements to it. The
first is the current state. So in this case, that would be this object here. And then it
also returns a dispatch. And that's a way to invoke the reducer function that we're going
to add. So let's create our reducer function. And the reducer function takes the existing
state, which I'll just name, state, and then it'll take some sort of action,
right, and that's what's going to be sent to that dispatch. So we'll just call that action.
So by convention, action is usually an object, and that object has a type on it. And then you
use that type in the switch statement to then mutate that state and return a new state based
on that data that you get with that action. So let's just start with setting that name. So we'll
create a switch statement. And we will switch on a type which comes in from that action. So when
we dispatch, we're going to dispatch an object that has a type on it. And then we'll create a
case. And let's call this one set name, because our first thing is we want to be able to set that
name for that input field. So let's do set name. And now we want to return a new version of state.
So we take all of the existing state, and then we have a name that comes in on a key called payload.
And that's kind of by another convention, you can really rename these keys all you want. But it's
very common to see type and payload. So the second value that comes out of this array is dispatch.
And we're going to use that when it comes to our input. So let's go create the input here. So
we're gonna have an input, where the type is text. And the value is the name that comes out of
here. So that right there, we get state name, and that gives us the State DOT name. And
then the onchange we are going to dispatch and then we're gonna give it an object
and that object is going to have a type. That type is going to be checked here. We're going
to pass set name, and then we're going to give it a payload and that payload is again that target
value. So the target of the event is this input. And then dot value is going to give you your
current value. So let's take a look see how we go and you know what just to check it let's go
and add in a div weary output the Current State All right, let's have a look. Okay, so we've got
our input field over here. Hello. Oh, nice. So what's actually happening here. So what's actually
happening here, let's kind of walk through it step by step is we have an input field, it has the
current name on it. And then every time we get a change event, which tells us we have some sort
of new text, we dispatch to this reducer function, a type of set name and the payload that then
gets given the current state, which we know is going to be this names as an empty array,
and then the current name, whatever that is, and then an action, that action
has that type in it set name. And then we just create a new object
with that state and that payload. But let's talk about that whole references and
scalars thing and mutating a reference in place. So let's just say that we're not going to do
that, we are going to instead just return state. And we'll just set the name to that
payload. Let's see what happens. Refresh, we type and nothing happens. And
again, this is because React is looking at the references coming out of use reducer.
And saying, hey, this matches the existing reference. So it can't see it's not going to
compare by contents, it's not going to look at the inside the object and say, look, the
name is different between these two things, it's going to look at the reference to the object.
So that's why we have to create a new object here. And then just mutate the fields that we want to
mutates, we return all of the existing fields, which mean all of names. And then we just
override the key for name and change it to whatever is coming in off that payload. So
now we need to allow for the customer to add an item to the array. So let's
create a new case called add name. And we're going to turn another new object, that
new object is going to have all of the existing state again, that includes names and names, but
we're going to override names to be a new array that has all of the existing names in it plus the
name that we send with the payload of this action. And I think actually, also, we
should just reset the name to air. So easy, there it is, we can actually
mutate multiple fields at the same time. It's pretty cool. Alright, let's go down
here. And we will make a button out of this. Call this add name. And with an onclick
handler, we will then dispatch add name. And you know what, actually, we don't really even
need a payload here because we already have the state. So let's go and just do add name. So this
is going to be state DOT names we already have just stayed on in there. Yeah, that makes more
sense. Okay, cool. So I think that's really clean, right? All you're doing is basically say, hey,
just add the name. Okay, let's take a look. Add name and now we don't really
know, maybe it added maybe didn't at least it remove the existing name.
So that's a plus. So let's go and see what we have that list of names to
see if we actually added a name. Hey, pretty cool. So as you can see, use reducer
is a nice way of managing more complex state. So in this case, we have an object that has two
keys in it, you can imagine you would have an object who have a lot of data in it a lot
of different keys, this would be a much nicer way to do that. And you could go and take this
reducer, pull it out of the component code itself, and then test it independently and not have to
worry about testing it through a React component. So I think it's actually a really nice way
if you have complex state to model that. Alright, now one more trick I want to show
you when it comes to use reducer, I really like this one. So let's go and call this name
list. And then we'll make another app component. Then we'll use namelist in there. Okay, so we're
gonna go and make ourselves a little user form. And in here we're gonna have two
input fields, first and last name. So let's make a div. And then within that we'll
have an input type of text. And at this point, we'll just say that Our value is going
to be some state and state at first, and then we'll have state DOT last. Okay, so let's use a reducer for that. So
we'll say use reducer. And we won't specify our reducer function quite yet. Let's go in and
set our initial state to have first and last. And then we'll get that
state as well as a dispatch. All right, great. Okay, cool. So let's
invoke user form here and see if it works. Nicely, I have two fields there,
but they don't do anything. So here's the trick. And I really love
this one. So what we're going to do is we're going to combine the state existing
state with whatever comes in on the action. Just like that, it's so easy. Fact actually,
we can make it just a little easier. How cool is that. And now what we
can do is over here, in our onchange, we can just dispatch with
whatever key we want to change. So we send the first then first overrides
just first, but everything else remains the same. And the same with last. So
let's give this a try around last. And now you have two fields. And let's prove
it out. Let's go and put two divs down here. First is first, is a dot first,
and we'll make a new div for last. Perfect. That's sweet. So you don't have to have
a whole raft of C functions. Using this little pattern here, you can manage very easily, large
object state and make all the mutations that you want. It's a nice pattern when it comes to use
reducer. Alright, so next up, we're going to take a look at two ways to observe state, use callback
and use memo. So now that we know how to declare state using use state and use reducer, let's talk
about three hooks that allow you to monitor state, that would be use memo, use callback and
use effect. And in this part of the video, I'm going to cover just use memo and use callback.
So let's talk about use memo because I think it's actually the most simple, yet somehow the
most misunderstood. So I like to think of use memo as use calculated value. So let's
take a simple example of a list of numbers. So here, we would define some state, we
got 1020 and 30 in there in our array, and we want to total it up. And in fact,
we want to use that nifty reducer pattern that we saw before. So how do we do that?
Well, we could just do something like this. We take numbers we call reduce on it, then
with that accumulator, starting at zero, we add each number in succession to that
accumulator, return the new accumulator, and then that gives us our total. So we
just actually just put that down in here. But of course, I need to bring
a new state. So let's do that. And I'll see like, oh, there we go. Total 60s
1020 30. Together is 60. Makes sense? Now imagine if you will, if this array was monstrous, huge,
crazy, huge 1000s of values, well, we wouldn't want to recompute that anytime that app rerender,
which is what's going to happen here every time react re renders our component, the entire
function gets called. So we want to do is we only really want to recalculate total when numbers
changes. So let's bring in our friend use memo or use calculated value, as I like to call it.
So as he's my my work, well use metal it takes a function and that function does the
calculation. So let's do that first. Alright, so far, so good. And then it
takes a list of dependencies in an array. And this is where a lot of folks
get into trouble. So basically, anything that you read from should go into
the dependency array. So in this case, we are reading from numbers. And that means
that we want to put numbers in the dependency array and what this will do is it will only
calculate this total only run this function. Anytime numbers changes, and in this case, case,
numbers won't change because we initialize it, but we don't actually add anything to it or
change it in any way. So let's run it again. And there we go. So there are two times when you
want to use use memo. And this is a really good example of one of them. The first time you want to
use use memo is when you're calculating any value and the process to create that value, it might
take a while. So any kind of complex calculation that you want to do, and in this case, numbers
could be arbitrarily large. So that qualifies, so no matter what the output is, if it's a number or
a string, or Boolean, another array or an object, that's fine, you want to use use memo, whenever
you've got a complex calculation that you don't want to do on every render, you
want to just be smart about it, you want to make sure that you only run it when
you need it. The other time you want to use use memo is when you're creating an array, or an
object. And that's because react compares arrays and objects by reference. And so it's important
to stabilize references, as we've seen before in the start of this video. So references
are really important, and you want to keep those stable. So let me show you an example of
that. So we'll start off with a list of names. Perfect, The Beatles, John, Paul,
George, and Ringo. Get up go by Oh, that's awesome. And now let's go and
sort those. So a great sort of names. And you know, it would just do an in
place sort. And then let's help with that. So now we've got the names, but you know what,
I also want to put the sort of names there. Now let's take a look. Okay, well, that's actually
just joined that all together using our comma. Okay, all right. So we've got a good sort of names
on here. But we actually have the same sorted list up here. So why is that the me we start with John,
Paul, George, and Ringo. And then actually names. Okay, so what's actually happening here is that
sort is doing an in place sort. It's actually mutating, named in place. So yeah, we're getting
a copy of the reference to that array, but that array has been sorted. So the first thing we want
to do is actually copy names before we sort it. And then we sort the copy. Alright, so now
this looks good. We have our original names, and we have our assorted names, and our original
names haven't been touched. So let's go back to the code. And let's see. So this is good. But
every time this component re renders, it's going to rerun this sword. That's not particularly
bad in this case, because AP is only gonna render the ones. So let's go and put in a use memo
around this. Again, we'll make this a function. And so what does this depend on? Well,
it depends on names. So names changes, we want to rerun that sort. So this use of use
memo falls into both categories. And when I think it would be important to use use memo. First, it's
an expensive calculation, potentially, you could have a very long list of names, and you don't want
to read run that sword on every single rerender. Awesome. It also falls into my second category,
which is that it results in an array or an object. So this is a really good use of use memo. Let me
tell you about when I don't think you should use memo and that's for very simple calculations, for
example, was about adding two numbers together. So now we got count one and count two.
I'm gonna go add buttons for those. All right, looks good. Let's go to trial.
Perfect. And now we want to get a total of these two. So right now, that'd be around
seven, right? So let's go in make a total. So I'm going to create a count total. And I'm
going to start off by using a memo and have an add count one to count two. And then
I'll just put that in the div down here. Hey, nice. Okay, cool. I'm gonna get back to
seven. How cool is that? All right. So this is not a good use of use memo. And it's because the
calculation is simple. And it results in a scalar number or a string or Boolean, so you don't really
have to use it at in this case, it's really just overhead in this case. So all you need to do is
just do an in place. Count one plus count two. That's it. So now that you know what use memo
is, let's talk about some of the myths around it. The first myth around us memo is it is somehow
connected to react memo to our in no way related, so I'm not sure how that happened. I guess
somebody was like us memo. They need to like, somehow react memo. But it's not that it's just
us memo is its own thing again think like use calculated value and react memo which memorizes
components and is a good performance enhancement in certain circumstances is just completely,
really unrelated. So the other myth that I've heard about use memo is it is a performance
killer. And I'm not really sure where that comes from, I think it might come from the CS concept
of memoization. So with classic memorization, you memorize a function, and then that memorized
function remembers every single set of parameters that sent to it, and only if it sees a new set of
parameters is a calculated new value, otherwise, it will send back a value from that cash that
it has and that cash could get huge get crazy, the potential number of parameters you can send to
it the combinatorial, and you just get like a big data in memory hit use memo doesn't do that
use memo is a single level memoization All it's doing is basically saying, hey, let's look
at this dependency, right? Is the dependency array the same as the last time that I saw it?
If it is, then I'm just gonna give you back the last value that you created. Otherwise, I'm gonna
allow you to create a new value for the new data. And then I'm gonna hold on to that, but it's only
a single level. So there really isn't any kind of performance or memory hit when it comes to use
memo. All right, let's talk about use callback. So use callback is another kind of misunderstood
hook. People don't use it when they should, should use it when they don't need to. Let's
try and demystify it a little bit. Okay, so we have this list of names, right, John, Paul,
George, and Ringo. And we have a sorted names use memo. So let's go and create a generic component
that sorts in a list of incoming strings. We'll call it sorted list, you give it
a list of strings, and it sorts them, and then displays them. So first, let's grab this
use mellowed out here, we're gonna need that. And so it's now the sorted list. And it will
depend on list. And then we will return a div that has our sorted list joined. Cool. All
right. So let's go down here and replace this sort of names with a sorted list. And
we'll give it the list, which is our names. And it looks really good. And it's doing its sorting
and everything still works. So looks good. So I want to see how often this sort of list runs. So
I'm going to make this into a curly brace function and just return that sword. And I'll put it in
my console log. Cool. And we can see that we are running the sword twice. But that's because we're
actually mounting the component twice. That's our React 18 thing. When you're in dev mode in strict
mode and react 18 Every component gets run twice. So that's not a big deal. But let's go and click
on all these buttons. And we can see that we're not getting run anymore. This component
is re rendering. I'm going to add that to sorted list render. And now we can see that
every time I click this count, we do get a sorted list render, you can see that's 20, right,
they're getting 20 times that call. By the way, this is console ninja that's putting
in the console in context like that. Really excellent extension
and it's free to try it out. So okay, so now let's go and say that we want
to make the sorted list a little bit smarter, we want to be able to give this sort function a sort
comparator. So let's say that you want to do your string sorting somehow slightly differently. So
we're going to allow you to have a sort function and we're going to send that
sword function on to sword and now we got to define that sword function.
So down here, we will define our sword function. And we will say that we are going to take two
strings, and we're just going to compare the two and we'll pass that sort
function on to our sorted list. Nice and So this sorting still works. In fact, we
can, let's see, you just multiply this by negative one. And now we get the inverse, we get Ringo,
Paul, John George. But we've actually messed up because we don't have our sort function in our
list of dependencies. Because if sort function were to change, we were to give it a different
algorithm, we would want a different result. So let's go and add that to our list of dependencies.
So now, let's hit this button a couple of times. And now we can see that every single time we
render, we also run sort. So what's happening there? Well, what's happening there is that every
time that we rerun app, which is every time we click that button, because we set the state, the
state then says, you need in queue a rerender, of the app component, that then reruns this
whole component all the way down the line. And we create a store function. And
then we pass it on to our sorted list. And now the sword function is the
same implementation each time, we're not changing the implementation. But we are
changing the reference every time. We're creating a new function every time that we go through this.
Now, is it any different if it were to do this? Is there some magic in React that will make it
so that that's not a problem? Oh, let's try. Nope, still gets called every single time. So
there's no difference between doing it in line like this. And having it called out like that?
So how do we stabilize the reference to that sort function, so that when we get down here
to our dependency array, we keep seeing that the search function is the same every single
time? Well, one thing to do would be just to pull this out of the function entirely. Up
there, now we've got this global sort function. Give it a try. Alright, so that works, we're
not getting a complete one to one match between rendering and running that sort. But I'm not
super happy about having this outside of the component like that. I don't think that's all that
clean. I'd rather have it where I had it before, right in the component. So how do we do
that? Well, we can use use callback for that. So you can wrap this function and use callback. And then what's the dependency right?
Well, the dependency array in this case, is empty. Because we're not actually using any
data that's in this function. We're not using total or names or count or any of that this
is just a simple stock comparison function, we just want to make sure that that reference
remains the same over time. So we're just going to use an empty dependency array there. That way we
only ever create sort func once. Let's hit save. Try it again. Hit a bunch counts. And there
we go. Now we have a stabilized version of our source function. And we will only ever call
sorted list appropriately if the list changes or the search function changes. But we're
not going to rerun it on every single go. So that's why use callbacks important. So when
should you use use callback, when you should use use callback if the callback you're creating
like unclick or the unchanged or whatever is going on to a nested component has a property.
So in this case, we're passing sword function as a property to the sorted list. And you
don't know the internals of sorted list. Maybe it depends on that sword function. And if
that sword function reference changes, it's going to go and update. So make sure that you stabilize
references that you send to a React component. If you're just using a simple HTML element like
input, you don't need to use use callback for something like onchange. It's overkill. The other
time that you want to use use callback is if you are creating a custom hook, which we'll get to in
just a bit. Anytime that you create a callback in a custom hook, you want to make sure that you use
use callback to do that because you have no idea what the component that's going to use that hook
is going to do with that callback. And you want to make sure that the reference to that callback is
absolutely stable over time. Alright, so the next thing we're gonna take a look at is everybody's
favorite hook use effect. So let's talk about use effect. Everyone's favorite hook. It's not
actually that complicated, but it does have a lot of foot gun potential. In fact, it's the hook
that is the one that's most often the culprit when it comes to infinite loops. inside of React
apps. So let's talk about how to do it right, and how to avoid those pesky infinite loops. So we
have a VT app here, it's called native user fact, it's checked into the GitHub repo in the source
linked in the description down below. And this is our starting point. So it's just a standard VT
app. Currently, app was nothing. But we do have some extra stuff in here in the public directory,
we got a list of names Jack, Jill and Jane. And then we have corresponding JSON files for each
one of our people. Not a particularly great API. But one of the things that we use use effect
for a lot is to make API requests. So let's do that. Let's actually use a combination of
use state and use effect to fetch the names. So first, we have to define our
data. And that will be our names. We'll start off with an empty array.
And then let's just print it out. Let's take a look. And now I currently have
names with nothing, because we have an empty array over here. So let's go populate that
array. Well, one way we could do that would be to do fetch right here. Let's go and get our
names at JSON. Then we get our response back. And then we set the names. He's easy,
lemon squeezy, we'll take a look. And there they are. Ah, oh, wait, hold on.
What's going on here? Oh, oh, wow. Yeah, we blew up. So here's what's happening. So a
render app app, then declares that state names, then starts a fetch, then that goes off and
asynchronously runs, we then return our HTML with our names in it. Eventually, this fetch responds,
we then get this asynchronous then where we get the JSON out of it. That again, asynchronously
responds, then we do this, then here, where we then set the names, which starts the whole process
over again, because what set names does as we know from before, it sets the names a state, and it
in queues, a rerender. So it redraws the names, which in turn, runs app, which in turn now goes
and gets the new names that we got. So yay, we're cool. Good for that. But then we start another
batch right away, and so are in an infinite loop. So how do we get around this? Well, we use use
effect. And use effect would allow us to say, hey, only go do this thing once. So what
does use effective? Well, it takes a function that is going to call once the Dom has rendered
or really whenever react wants to call your use effect, but not going to call it right away,
it's going to hold it and then call it whenever it wants to when the dependency array changes.
So let's put our fetch inside that. And then for a dependency array, we'll just use an empty
dependency array. We're not depending on anything, we're not reading anything inside of this
user fact. So we don't have to put anything in the dependency right? So let's save that
out and see, is this gonna work? thing? Oh, it works. And it's rock solid, stable. How cool
is that? Yay. Now it actually does go and fetch names dot JSON twice. So let's talk a little bit
about why that's happening. And why that's not really a huge problem. So what's happening is with
React a team, every time it renders a component in dev mode, with strict mode enabled, it mounts
it, which renders it, it unmount it, which, in the case of a use effects should call
a cleanup function if we define one, but we haven't defined one here, and then
it remounts it again. And that remounting calls that use effect again. So we get called
twice. And a lot of people freaked out about this and wasn't very, we're very happy about it. But
that's what it is. So if you want to not do that, you can actually disable that by removing
strict mode from your app over in the main dot JSX. Again, this only happens in dev
mode. It's not gonna happen in production, but I do got tweaked about it. So
there we go. So let's try it again. It refresh and now we only get named JSON, the
ones right now the use of what we have here is not an infinite loop. This is a saw to use
effect, a good pattern. Let's go and kind of build on this by taking names and turning into a
list of buttons. And when we click on the button, we'll go and load the corresponding data. And
that will show us how to use a dependency array with our use effect and do it safely. So we'll
start off by mapping our names into buttons. We'll turn these into buttons. So now when we
click on one of these, we want to say that that is our new selected name. So we need some state
to store that. So let's call that selected name. And we'll start off at null. And
then if you click on that button, we're going to set that selected name
to whatever name you just clicked. And just to check if this works,
let's put that in a div down here. Jack Joel Jain perfect, works great. Okay, so now
we want to do is we want to go and get the data when this selected name changes. So let's go and
build a use effect where we look at selected name. And then we fetch whatever name that
is. So we'll use a template string here. And then we'll give it the selected name dot JSON.
And what's the so we need some place to store the data. So we need a data for that selected person
will call that selected name details. And so down here, instead of set names with the response back
from the JSON, we'll do set selected name details. And we'll just take that data cool.
And now we've got our data in there, I'll take a look. So in the div down here, and we
will JSON string five. And because it's an object, and react doesn't like when we just render
objects directly, so let's JSON stringify that put in our selected name details and see we get
all right, so we start off with no, that's good, because we start off with our selected name
details as null over here. And then as you cook on Jill, we set the selected name to Jill, that then
triggers this use effect because this selected name, which is now Jill, is different from what
we had before, we should know. So we have an array with Nolan it now we have an array with Jill
in it. And so that triggers that use effect. But here's an interesting little side note,
we also got a no dot JSON request. So what the heck's up with that? Well, what happened there is
that we started off with the selected name it No. And then we came down here and react
said, Hey, cool. So we're loading. We don't know what was in that dependency right
before root didn't have a dependency right before. So whenever you're gonna have in here is gonna
be different. So the dependency array had an array with no one it. And so it ran you that
our use effect with a selected name that No, which is not what we want. So all we need to
do to get around that is then to just bracket this in a an F, and say, Well, hey, only go get
the data if we actually have a selected name. So there we go. But now that
I've shown you all this, this is actually the wrong way to do it. Because
really, we are responding to a user event here, we're doing this onclick we have our data right
there, what we should do is we should do it right in the callback. So instead of having
the selected name, and then the use effect, what we should do instead is create a
callback, called like on select name. And this is going to be a name. And
then we'll just go and fetch that name. Now we can get rid of all this use effects stuff. And over here, we will just call that
on select a name change with the name. And let's see how it works. Perfect, and very
reliable and no potential problem with use effect. And this is something I see a lot where folks
use a combination of state and to use effect, when in reality, they're just responding to
some user interaction and they should just go and do the action. Right at that point. It's the
simplest thing to do. And it's the right thing to do in this case. So you really want to as cool
as US fact is limit the amount that you use it to justify things where you need it, like,
for example, this use effect up here. Okay, so let's talk about when use effect gets a little
bit hairy. And that's when use effect depends on data that it also writes. So to experiment
with that, let's create a stopwatch component. And what this stopwatch is going to do is
it's going to have a an incrementing time. So it starts off at zero and it just
every second goes up by one. So return a div that has time with a timer on it. So far, so good. So let's
bring that down in here, and we'll use it. There we go. Time is zero. Cool. So what do we
need to do to get this going? Well, we need to use a set interval. So now we know that we're going
to put a set interval right here, and just set the time to the time plus one, and then do 1000,
that just like that fetch that we had before, you're going to run into an infinite loop. Because
every second, we're going to set that time, that setting at the time is going to force
a rerender of the entire stopwatch function, which is going to get the new time, Yay, it's
gonna be one. And then it's going to run another set enroll, which is going to create lots and lots
and lots and lots of intervals. So we don't want to do that. Well, we want to go and create one
interval. So let's go and use use effect for that. And we know from before that we want to
create an empty dependency right here, because we only want this
interval to get created once. So let's try this out and see
this works. So I'm gonna hit Save. And now we go from zero and we got a one. We stick
there. So what's the deal? What's what on console log, and see what's up. So we'll do console dot
log. And we'll just put in time, well, what's time, because that should be going up and up and
up. Right, that number. So it's it save to go, zero to one. But if we look back at our code, we
can see in the console, which is out here, with console ninja, we're just getting a time at zero
over and over and over again. So what's happening? Well, what's happening is that we first
initialized this effect when we got our initial component render, and at that time,
time value was zero. And what JavaScript did was we created a closure here, and we captured
time, zero. And so now inside of this function, time is forever going to be locked at zero. So
what's one option? Well, we could go and add time in there as a dependency so that when time
changes, we rerun this, and we get a new value for time. But that's going to run into the same
infinite loop problem, because we're going to go and create interval after interval after interval
after interval. Another option is that there's a secondary way to call a setter on use day. One
way is to just give it the new value. Another way is you give it a function, and that function
takes the previous value, and then you get to return whatever the new value is. So in this case,
that would be time plus one. So let's hit Save. And now we have a working timer. And if we
were to go into here and put in a console log, we would see that this number for time, the actual
current value goes up and up and up. And in fact, I can make this a little bit easier to
understand by just putting in like, for example, like T to distinguish it from time, because time
is captured, then this function, but T is just the current value for time. And there's one more
thing to know about use effect. And that's that the function that you give us effect can return
a cleanup function. And that cleanup function we had called whenever the all these effects
is getting kind of unmounted or gotten rid of, and the new use effect is coming in. So in this
case, what we're going to want to do is we're going to want to clear that interval that we've
created. So I'm going to capture that interval ID and then I'm going to return a cleanup function.
Or I clear that interval. And that makes this a solid timer interval. I asked actually this
question a lot when it comes to interviews and if you were to give me this code, probably mine
is that console Ugh, definitely give you a passing grade on your interview. So of course, there's
a lot to understand and know about you the fact but use the fact that is really important as
you build your own custom hooks. Or if you just want to use React Native state management as the
state management foundation of your application, use effect is the kind of thing that you're going
to really need to become familiar with. And make sure that you are very comfortable with it, yes,
you can get yourself into some serious hot water with use effect. But in all honesty, it is an
understandable thing. And when you understand the fundamentals of JavaScript and how they work
with use effect, it actually is a lot less spooky, so just spend a lot of quality time with it.
And I swear, you will get a lot better at it. I mentioned early on that there was this other
way of storing state in a component called use ref. So we'll take a look at that next. Okay,
let's take a quick look at use ref. It is one more way to associate state with a component
in React. The interesting thing about use ref, though, is that when you change the value of a
reference, it doesn't actually cause a component rerender. So that can be convenient in some cases.
But there's actually two ways that folks use use ref. So let me show you the first way, the most
common way, and then I'll show you about the state management side of it. After that. This is the
native use ref folder in our GitHub repository of applications. We're looking over there. So I'm
gonna bring in use ref. And the first thing I'm gonna use it for is, I think, the most common
use case, which is to get a reference to an HTML element. So in this case, we'll create an
input element and then get a reference to that. So we have this text element. And now we want to
set focus on that input when it first starts up. So I'm going to create a ref, a reference to that
element by using use ref and then just starting off with the initial value of No. And then I will
use ref equals, and then just give it that graph. Now let's see if this works. Okay, it looks
good. We can go and add stuff in there. But what we want is we want that input to be
initially given the focus, so they get the little blinking cursor in there when it starts
up. So how do we do that? Well, we need to one know that the reference is defined as something
that means that the component will have rendered, and then we will have gotten a reference to that
element. And the way that we know that is if we use a use effect, because use effect runs after
all that happens. So let's bring in user fact. And we want this to only happen once. So what
do we do, we give it an empty dependency array. And then within that dependency array, we just
focus on the current. So what is current? Well, when you have a reference, you have a current
value associated with that reference. You don't just do input ref dot focus. Because input ref
is itself, just a pointer to current and current is the thing that you can set or read from. So
let's hit save, see how we do. And now anytime that the page refreshes, we automatically
set focus to that element. So super easy, nice. That is the way you get access to elements
in React. And that's the primary use of user. But there's another use, and that is to maintain
state without doing any updates. Let's build out an example here. So we're going to have a list
of names. And then we're going to use this input fields to go and add a new name to our list of
names. So let's get that all set up. So we have our use date with our empty array of names
to start, let's go and put that into a div. Cool. So now we need a button
that we can use to say, hey, add this name that we just typed into
this list. So let's create an on ad name. And we'll assign that to the onClick. Now remember
from before, when I talked about use callback, we're not using a use callback here because
I'm just passing this on Add name function to this HTML element is not its own React
component. So I know exactly what's going to happen with that unclick it's not going
to create any kind of referential identity problems like we would have with passing that on
Add name to a nested React component that may do I don't know what was that on Add name. Now
we need to do is we need to go and set names to the current names plus, the value of this
component was pretty cool, right? Because we already have a link to this input. Or we can just
reach out and grab it. So we can say, okay, cool, get the value from that component. This is called
an uncontrolled input in React. And it's actually the most efficient way to manage an input.
You don't have to use that set and get value. And then one last thing we can do is we can just
set that value to an empty string. Cool. So let's give this a try. Oh, looks like it's blown up.
Let's see why. So I got my name inspector console. We didn't bring in new state. Make sense?
Okay. So let's get back over here. Use state. Cool. And there we go. All right. So Jack, and
name Hey, wow. So what about use ref? In this world? Well, let's say instead of having just the
names, each one of these had like Id one is John, and Id two is Jane. So you have an ID and a name.
So it's not just a name, it's structure. And let's go make names. Sing that tune. So this is going to
be name. And then name dot name. On exactly great, fine. Okay, looks good. So now there we go.
But now when I do add Name, foo, this is gonna blow up because add name, I'm just adding the
single value, right, I'm just adding a string, what we really need to do is have an ID with
something that's a 10. Right now, and then a name. There we go. So we want to track this ID, and we
want a an incrementing ID auto incrementing ID. So that's where something like use ref is going
to come in handy. We don't necessarily want to use use date for that ID because we don't really
care that the UI gets updated when we change that value. So we can just manage the ID using a ref.
So let's create that Id ref by using use ref and then starting it at one. And now down here. We can
just use ID ref dot current. And we can just treat it like a value i current Boss Boss. Let's take
a look. Current Boss, boss. Nice. And then down here. Current Boss, boss. Awesome. And just to
check, let's go in add in the name.id down here. All right, so there we go. Yeah, one is John. Two
is Jane, just like you set up right here with the one and the two. And then we have Jack, let's
see what I get. I get three. How cool is that. So you can set this value current without forcing
a refresh of the React tree, which is great. Of course, we matter. In this case, since in all
honesty, I just on Add named as a set name, which in turn actually still rerender the component but
I think in some cases is valuable to hold state in a use ref like this. And it's just good to
know that that's there, if you need it. Next up, we're gonna start finishing up our look at Native
react state management, by getting into context, and also creating your own custom state management
hooks, exciting stuff. And that's going to culminate in us building our own pokimane search
application seems like it's time to start wrapping up React Native state management, before we get
into indirect state management, like React query, and and state managers like Redux and Joe
tie and all those. But before we do that, we need to talk about context. And we also need
to talk about custom hooks, because those are the ways to kind of package and redistribute
state in a native react state management model. We also need to talk about TypeScript. So you
might have noticed that I haven't been using TypeScript up until well, now. And the reason
is, because I want us to focus on the model of state management and learning about the reactive
nature of state in the native react state model, declaring, say, using new state and use reducer.
And then monitoring state using use callback, use memo and use effect. But now it's time to
talk about TypeScript. Because in reality, you're probably going to want to use TypeScript when
you're using almost any state management system, including React Native state management.
So from here on out, we will be doing TypeScript. So now the native context app that
you're looking at right here is basically the same thing we've been looking at so far. Except that I
use the react dash TS template, invite the bullet. So it's the TypeScript version. And I've also
added tailwind and a Pokemon JSON file that has a list of Pokemon in it, including what was or which
apparently is a grass and poison, and Pokeyman has all these stats. And we'll be using this
datasource going forward, as we take a look at how to actually put all of what we learned into
practice. So that starts with learning about custom hooks. So let's go and build ourselves
a custom hook to go and get that pokimane data. So what are the things we're no we're gonna need,
or no, we're gonna need state, we're gonna have to hold it. So let's bring in use state. And we
also know that custom hooks start with the word use. And so I guess I'll just say use Pokeyman as
the name of this custom hook, and custom hooks are implemented as functions. So let's create our
use boogeyman function. Now, I don't think it needs to take any arguments, we just have used
boogeyman, and it will have a list of Pokemon that it will then return. So now we have our
state, we'll initialize it to now in fact, actually, let's be nice, let's initialize it
to an empty array. The next thing we need to do in our use Pokemon hook is to use an effect
to go and do that fetch. So let's try that out. So use a fact takes a function,
and also takes a dependency array, we only want to load the Pokeyman once, so
which dependency already we use, we use an empty dependency array. So now let's do our
fetch. And we'll get our local Pokeyman json file which will then convert the response on and
take the data, and then we'll set the Pokemon with that data. But of course, we don't
have set pokemons I was gonna add that. And now just give it the data. So now we have
a problem that we don't actually see yet, which is that that type of Pokemon
isn't what we expect type boogeyman is a never array. So what does
that mean? Well, it means that TypeScript can't infer what this array is
going to be. So it defaults to saying, well, never can have an empty array, it has to be empty
for its whole life. That's the only thing that I can guarantee about. So we need to define what a
Pokemon looks like. And then tell you state that is going to be an array of that. So how do we do
that? Well, we define an interface for Pokemon. So we look over here, Pokemon JSON and got ID
name type, which is an array of strings. And that corresponds to this interface, ID name, type,
which is an array of strings, and then all of the parameters for that book came out. And now with
this interface, we can then tell you state that this is going to be a pokey Monterrey. And the
way that we do that is we use the generic syntax, and then we put in a Pokemon array. And now if
I look over here at Pokemon command, Caveman AI, we are getting back a pokimane array. But if
you're like, shouldn't have been able to infer the type of the Pokemon from Polygon JSON. I
mean, yeah, it's sitting right there. Well, no, because we get Pokemon JSON at runtime. So it has
really no idea what the structure of that is until we tell it what the structure of that is. So this
is your first lesson in native react hook typing. Honestly, it doesn't get a whole lot more complex
than this, you notice that there is no typing on user fact, there is no typing on this use Pokeyman
hook, we could add return typing if we wanted to by just saying we're going to have a list of
Pokemon, which is going to be either an array of Pokemon or no, but honestly, par is going to
have an array Pokeyman. And but that's it. So you really don't have to use TypeScript a lot
when it comes to react state management. Okay, so let's see what we're getting back. Let's do
use pokimane down here, and we'll get our broken and the easiest way to do this and just find out
is this a JSON stringify it and let's see we get and we get a whole bunch of data. Nice.
Love it. So now we got our data source. Let's say that we want to go and make
a Pokemon list that shows Pokemon. So it's gonna take Pokeyman as a prop, and that
Pokeyman prop is going to be an array bogeyman. And you know what, let's do it a little bit
nicer reformatting. And this will create a div. We'll map through our Pokeyman
we'll create a div for each one. And let's try this out. So we're going to do
Pokemon list and then give it a Pokemon. There we go, a nice list of boogeyman a long
list above, what if we don't want to have to prop drill everything, because here we're doing
what's called prop drilling, we're taking data, and we are sending it down as props. Maybe this
Pokeyman list is deep inside of our hierarchy of React components. And we don't want to have
to go and grill that Pokemon property all the way down. And maybe we have a bunch of different
components that use boogeyman and we just don't want to have to shuffle that data all round is an
easier way to do that. And the answer is yes. And it's context. That's what we need to do. We
need to provide this put your own data down to anyone who wants to use it. And the way that
we do that is we route it through context. So we need to create some context. So the first thing
we need to use out of React is create context. And you know what, I'm just going to start off
looking at context, just by creating, like, very simple context, we'll just say like
a theme provider or something like that. So we're going to create a theme context. Okay, so now how do we use this theme
context? Well, we need to wrap components that consume the context with a context
provider. And when we do that, is we instantiate a theme context dot provider. So
automatically, when you do create context, you get back a dot provider, and it's a React
element that you can use to provide value down any specified value by just specifying the prop for
the value. So in this case, we're gonna say dark is the value the current value, it starts off
defaulting to light. So now how do we consume this, let's just give it a try. Let's
go over into pokeymon list and try and see if we can consume theme context.
So I can show you how Rao's around. So we'll bring in the use context
hook, which is how you access context. And in this case, we're just going
to get the theme by using that use context hook and pointing it at that theme
context. So let's see what the theme is. And the theme is dark, nice. If I go
over here, and I change that value to light, our theme is light. And we can see that we
don't actually have to prop drill down the theme. We just have that theme context. And wherever
we want to use that theme. We just use context, we give it the context, and we get
the value back. Okay, so obviously, we don't want to do theming. Or maybe we do,
you can do that for yourself if you like, what we want to do is use this pokemon data.
So we're gonna provide this pokemon data down to the rest of the application through this
context. So I'm gonna call this pokemon context. And okay, so what are we gonna put in there as
a starting state, what we could do is, we could say that we have just a, an array of Pokemon,
because that's the output of what is of this use Pokemon here. And let's see, does that work? So
Pokemon context, let's go down here to the context generator, look at my context was given a value
value is going to be the output of us Pokeyman. Looking pretty good. Now, we don't have put
him on there. So we actually get rid of it. And now we can pick up Pokemon from the boogeyman
context. And so I'll rename this pokemons GTX. And if I look at that, then the context
is an object where we have Pokemon. But it's a little easier. This is beauty Pokeyman. And there we go. Well, we don't have a theme, was
it? Let's get rid of that. All right. Looks good. Nice. So now using context, we can see that we
can move around all that data without doing any properly. But there's a few things that I don't
like one, I don't like to use context directly. So I want to make a hook that gets us access to
that context data that's named appropriately. And unfortunately, use Pokeyman is kind of camping
on that name, because use Pokeyman would be a really good name for that hook. So what I'm
going to use, instead of use Pokeyman Well, we could do something like use Pokemon source
that kind of works through that. So down here, this is going to be the source hook that has the
data in it. And then we can do something like, define us Pokemon, by just returning
the US context from the Pokemon context. And now down here, we can just use bogeyman.
Alright, it's starting to look a little cleaner, I like that. And now there's one more fix up, I
think we should do around this context sharing mechanism, before we get into actually kind of
fleshing out this app and using all of the other hooks that we've seen. So the first thing we need
to do is get the typing right, on create context. So the way that we do that is
to use that generic syntax. And what are we going to have in our context,
where we're going to have the return type of the US Pokemon source function. So this is us poking
around source, we're gonna have the return type of that. And it's either gonna be that or undefined.
So now we can just set this to undefined. Now, the problem is that the
output of us Pokeyman is either all of the cool stuff that we got from us
boogeyman, source, or undefined. And so down here, as we use it, it's like, Ah, you could be
undefined dude. And you're not handling that. But we know that it's always going to be valid,
we know that we're always gonna have a value. So one thing we could do is, we could just use an
exclamation point that basically tells TypeScript Hey, it's always gonna be not undefined.
But another thing I've seen people do, and I'm kind of torn on whether exactly this
is the right idea, but I think it's fine is to instead of allowing for undefined, so we just go
back to something like this. We just take an empty object. And we can take that empty object Intel
and why basically, to Typescript and tell it that it is a return type from that use pokemons source.
So the way that we do that is we say as unknown. And then as the return type of use pokemons source
comm I have to go through this two step with TypeScript. You know, honestly, once you get this
set up, you won't really see most of this typing, and you'll just be using it and it'll be fine.
So little hacks like this aren't necessarily that tough, you're only gonna have these a few
places in your code base. Alright, well, I think we got a pretty good start. Here, we have
our Pokemon data. And we've got tailwind, we have a bunch of knowledge about these other hooks that
we can use. So we can make an application that gives us a searchable Pokemon index. That even
looks pretty cool. Alright, we'll do that next. Alright, we're starting off at exactly the
same point, I've just taken the native context directory and cloned it to native Pokemon.
So if you're following along on the GitHub, this is the native Pokemon app. And what we
have is we have a list of the Pokemon cool. So the first thing I want to do is kind of
refactor this a little bit, it's get a little messy. So I'm gonna go and take all of the
stuff that's related to the data the store, and I'm gonna pull that out and put it in
its own file, we'll call that store dot TSX. Pop that all down in there. Alright, so what do
we need out of here? Well, we need most of it, actually, we need to use boogeyman source. And we
need put you on context. And we need use Pokeyman. Cool. So now let's go back over
here, and get rid of all of that. And then import it from that store. Not too shabby. Let's hit save, try, refresh. Refreshing. I love it. But there's one thing I
am not quite sold on. I don't like that the app is having to maintain this connection between us
working on source and Pokemon context provider. And I think we can kind of hide that elegantly. By
making a Pokemon provider component, I think it's actually pretty easy. So let's go over here to
our store. And then we will export a new component called Pokeyman provider, which will take children where those children are a React node type. Now
put our children in there. And now we can get rid of the export of the Pokemon context, as
well as the export of the US Pokemon source. Nobody else needs to know about the US. So let's
bring in Pokemon provider over and out on TSX. And here we go. Nice. Again, let's try it out.
Very good. Cool. So let's make this a bit swanky. Right. So the first thing we're going to do is
we're going to wrap the whole Have in a centering tag. And tailwind, that means setting the max
width of the screen and then auto, the x axis. So MX auto, kind of bring it in from the sides. Let's
take a look at that up. Nice, very cool. So now it's kind of in a little bit. So now we're gonna
model pokeymon in an HTML sense as a list item. So in order to bracket that, you have to have a UL
or an unordered. list. And so for our tailwind, we're gonna say that this is a grid. And let's
take a look, see how that goes. Pretty good, nice. And then we're gonna bring in a bunch of HTML,
which is going to format our pokimane. And, of course, all of this code available to
you in GitHub for free. I'm gonna type it all in because there's a whole bunch of
tailwind, but I do need to go and add a key. And let's take a look. Wow, that's pretty
cool. So the next thing we want to do is have a search box. So I'm going to create a
search box up here. And we're going to provide for searching so let's go and create a
component for this called Search box. And we will return input tag in there, give it
some nice tailwind Ng, and we'll take a look. Ah, whoa, that's good. Looking already. Nice. So
now we need a place to store that data, right, we need to hold the search term. So let's go over
here and take a look at our use Bergamot source because I think that's a good spot for it. Now,
we could just add another item in here for search. And in fact, actually, you don't even need
to specify string. They're just that will do. But I do want to show how to type use
reducer. So let's use a reducer for this. And let's see how we go. So we're
going to use use reducer. And the initial type is going to be a
an array of Pokemon and a search term. Fair enough. Now we need to bring in user
reducer. Cool, okay. And we need a reducer, right. And that's going to take two things is
going to take the current state, and it's going to take an action. And we're gonna have that
big switch statement in there. But currently, it's complaining about our lack of typing.
So let's go and add some typing here. So let's first type state. And we'll
call this the put you on the state. So what is that? Well, that is going to be an
array boogeyman and then the search string. Fair enough, that's pretty easy. And then the action
was was put together some action. So the first one we're gonna have is like the set of the Pokemon
itself. So let's call those Pokemon actions. And it's going to have a type where we say set Pokemon, and the payload
is going to be an array Pokemon. So now we just need to start implementing on this, so I need
to switch on that action and set that pokimane. So we're gonna return the existing
state with the new payload. And that's it. Yeah, pretty good. So that's how
you type a use reducer. So now the output of that is going to be the data and the dispatch. So let's
get that out of there. The first parameter is going to be that object. And from that parameter,
we're going to grab the Pokemon and the search. And then we're going to grab that dispatch. Oh, okay, looking good so far, but now down here that set Pokeyman. So we need to
replace that with that dispatch. And what is the type on that will set Pokeyman? And was
the payload, the data? So now coming out of this function, we're also going to return
the search string. And we just return it and have a look at us bogeyman and say, What are
you getting out of there is getting the array Pokemon, and that's our string. So let's go use
that. So we'll go over here to our search box, we will grab our user schema and instead
of boogeyman, we'll just grab search and set that as the value. So to see this all
wired up, let's do something fun. Let's call this set the initial state
something foo. Yeah, perfect. So now we need to have a
way of setting that search. So let's uh, Add another
option for our postman action. And we'll call this one set search and give it a string as the payload. Now we need
to switch on that type and return an updated state that has the new search in it. Easy
peasy, lemon squeezy. But we need a way to actually dispatch that. And we're not
exposing dispatch. So what do we do? Well, we need a set search function. Now we need
to return that. So this set search function is going to take a search string
and return nothing a void. So how do we define that?
Well, we can come down here, we can say that set search is a search
string and dispatches a type of set search with a payload of that search.
Cool, and then we return it. But I didn't say something
early on about use callback, and custom hooks that you should always use use
callback in custom hooks when you're defining a function that you're returning. So let's
do that. Let's bring in our use callback. And then down here with set search,
I'm going to call use callback. And what do we use for the dependency array? Well,
we use an empty dependency array because there are no dependencies. There's nothing going on in
here except for the dispatch, which is a constant, and then search, which is given as a parameter.
So there's nothing we need to depend on. Okay, so let's go take a look over in our app. And we will do set search on that value, and
then we need to bring in set search. Cool. So that probably works. I'm hoping we'll work on
the idea that at work. So let's get rid of this while we're here. And we'll go back up to our
store. So now we need to have like a searched set of Pokemon. So we have our
Pokemon, we have our search term, we need to calculate the array
that falls within that search. So when we think about using a calculated
value, what do we use? We use memo. So let's go bring in our friend use memo. And so we'll
create a new array of the filtered program on using them ml and will return a filter where
we take any poking around with a name includes that search. So what is the dependency
array going to look like in this case? Let's have a think about that for a second.
So what are we reading from here? Well, we're reading from Pokeyman. So that's clearly
got to go in there. And we're also reading from the search, because we're including
search there. So let's give that a go. Now, what do we do with filter bogyman? Well, we can do
is we can just say, well, the poem on the return isn't the original whole list of Boogeyman.
It's just the filter boogeyman by just saying filter Boogeyman. So now let's try and filter this
down to be you lb, and we have just the Baltimore How cool is that? See, that's the
reactive nature of React state management. You're creating this connection between
the original data source Pokemon, and that search term. And then when either of
those things changes, this use memo triggers, and then we get an updated filter Pokemon. So
once you get those relationships set up, right, it actually is a very elegant system. Okay, so
let's just take the top 20 here, because this gets a little crazy, and we've got to eat 800 of
these things. So let's just slice off the top 20. Now make a little bit more efficient.
Alright, so another feature thing, I want to make this case insensitive. So the way we do that
is we would lowercase everything and compare that. Cool, and now if I go over here, and I
type in bu LV lowercase, or whatever case, it finds all sorts of case insensitive. That's
nice. And then I guess the last thing I want to do is I want to sort the Pokeball on the
way out, and I think that's another good use for use memo. So let's go and create
a sorted version of the filter Pokeyman. So we're gonna take that filter bogeyman and we'll
just sort Under the name, so we'll do a dot name. And then locale and compare that to be dot name.
So what do we need to depend on? Well, the only thing we're reading from here is filter Pokeyman.
So let's add filter Boogeyman. And now we've got started to bug him on. Put that in there for alpha
Pokemon. And cool. Now we have a sorted list. So let's see. VOB are you Oh, yeah. Okay, there you
go. So, B, G, S T sorted. Alright, so this is very cool. We've learned all about reacts native state
management system, we've used a lot of it in this particular example, I certainly recommend if
you want to, to stop the video at this point, work through this example, get comfortable with
it. Because this set of hooks, use a use reducer use callback, use memo use effect, that is the
underpinnings of state management in react in 2022. Everything else kind of fits on top of that.
So if you're using indirect state management, like React, query, react form, or react
application, those work in conjunction with these hooks. If you're using something
like redox, or Joe tie, or recoil, or Zustand, you're going to use a combination of that, and
also the native hooks built in. So it's really important to get a foundation set where you
really feel comfortable with all of those hooks and in particular, obviously, use the fact that
it trips a lot of folks up. So now we're gonna get into indirect state management by taking a
look at one of my favorite libraries react query. So now that we understand the foundation of
native react state management, it's time to take a look at third party libraries and see
how they can help us make our lives easier. And we're going to take a look at two, we're gonna
take a look at React query and react location. Let's go take a look over their websites.
So here's our current site, obviously, in our 10 stack query site. Now, react
location react query are both part of hinterlands Lee's hand stack, it's really cool.
So react query is primarily designed to do is allow you to easily query data from a server
as well as post data to a server to mutate it can be used actually, to manage any promise. So
it's a generally awesome library, there's another one called SW R from versal. That's also really
good. I think react query is currently like 12k, SBRs, 4k, so you can decide for yourself which
one you want to use, they're fairly similar. React location is a 10 stack version of React
Router, we're going to use that because we're going to turn our single page app into a multi
page app. So let's start off with React query and make it a little easier on ourselves to query the
Pokeyman. So let's go over here and take a look at the inspector and look at the network. And
we can see that when we refresh, we're actually getting pokeymon dot JSON twice. And this freaks
a lot of folks out. But it really just as a matter of being in development mode was strict mode on
so why does this happen? Well, if I look over here in Maine, we can see that react strict mode is on.
And in React 18 strict mode, what happens is react automatically when it first gets your component
it mounts it and then an unmount set, and it rebounds it and the idea is to help you look for
any leaks that you might have particularly in use effects that you don't close out properly. But
the net result is that things like use effect, which we use down here. If they have
well, any dependency, right, honestly, but people believe that the empty dependency race as
this is only going to happen on load or on Mount. And what happens is use effect gets run twice
because you mount unmount and then rebound. So actually, the contract is true use effect with
an empty dependency rate only ever gets run once on a mount. But it just happens that react
18 in strict mode with development mode on actually mounts you twice. So yeah,
that's why you get two calls. But hey, it's fine. Let's go and replace basically
all of this fetch code with React query. So how are we going to do that we're going to
start by bringing in the React query library. Get started. Let's see we need to install. So
we're going to yarn add tan stack rack weary and then I'll bring up the site again. So now what we need to do is we need to on the
app side build a query client provider as well as a query client Now that query client is
basically a cache. So that's actually going to help us with this double problem. Because when
we ask react query to go and get that put you on JSON for us the first time, it's gonna
go and get it. And then the second time, it's gonna say, Hey, I've already got this
thing cache, you don't need to worry about that. And it's going to handle that for us.
So how do we get that process started? Well, we got to bring in the Create Client provider, as
well as a great client creator from the 10 stack. And then we'll create our query client.
And then we'll wrap our whole app in a query client provider. This is again, like
context thing, like we learned earlier. This is just a context based provider that is
managed by that tan snack, react query. So let's give this a try. See if it works. Hit refresh, and
everything is still refreshing. Cool. So let's go over to our stored at TSX. And see how we can use
this well, we can use this by bringing in US query from pans dat. And now down here, we're gonna
make some changes. So I'm gonna get rid of this, as well as the Pokemon, because we're not going
to manage the Pokemon ourselves anymore, we're going to use canned stack for that. So we're gonna
get rid of anything that would be setting Pokemon. And initializing it cool, awesome.
And we'll get rid of our use effect. And we don't need to set Pokemon. Alright, looks good. So now, we can use use query.
So what what is use query do. So now we can use use query. So let's bring in use query. And it
takes a bunch of parameters. The first one is a query identifier. So put an array which says
that this is going to be the Pokemon array. So that uniquely identifies this particular
query for caching purposes, then you need to give it a fetcher. So we're going to give it fetch
Pokemon dot JSON. And then we're going to get the JSON from that request. So we have to provide it
with the fetcher. And it actually doesn't do that for us, which is kind of interesting thing. But
again, use query is more of a promise watcher, it doesn't really care what promises you throw at
it. So in this case, we're throwing a fetch at it, which is the query, that isn't the title of the
talk. Okay. And then the last thing we need to do is give it what the initial data is. So when
it's not got the request done, what do you actually want to put in there in the meantime,
and we'll just put an empty array in there. Okay, that's cool. So let's go and
get the data out of this. So we'll get an object from it. That object contains
data. And we can just rename that to Pokemon. But this is actually typed as any currently.
So let's cast that to a Pokemon array. And now we have an array of Pokemon. Let's give
it a try and see we go, refresh. Nice. It's that easy. Literally, how cool was that. So we don't
have to have that use state or use reducer that holds that data, we don't have to have use the
fact that go gets that data, we can just use React query, and then let it manage the data. And
that's what I mean by an indirect state manager is react queries primary job is to manage that
promise. But in doing that, it also has to get the data from that promise, which it retains, and
it stores for us. So it manages part of our data. So let's go see if it's actually solved our double
network call problem, go to Network. And yeah, now we're only getting that Pokeyman JSON, just
the ones even in React 18 in development mode. Alright, so now it's time to turn our awesome
single page app into a multi page app using React application. And in doing this, we're going to see
that the URL is going to contain part of the data because what I want to do here is I want to be
able to click on one of these and get detail about Beedrill or blast noise or whatever it is. And
that's going to go to a slash Pokeyman slash ID. And that ID is going to be part of
our data, right? It is part of our data model for the application. So let's
go and see how we do react application. So go over an installation, and we see that
all we need to do is bring in React location, stop server, paste that line in, start the server
again. And so what do we need to do? Well, we need to bring in a few things from our React location.
We need to bring in a link. That's what we're going to use to do the client side links or any
Use outlet, which is a way where you can specify where the content of the route is supposed to
go, which is effectively like the query client. So we're going to create one of those like that,
we're gonna use the router, which is a component that wraps the application gives us that context.
And then we're also going to use use matches the way we can get the parameter from the route. So
the next thing we need to do is give ourselves a list of routes. Now routes are listed as an array.
Each array has a path and then an element that you want to render. When you go to that particular
path, there's actually a whole bunch of stuff around this are as loaders, everything else,
there's children elements, that is a really a much more robust system than what I'm showing
up here, I just want to kind of show off sort of the basics. So in this case, our current route
is slash, and what we want to show in there is our search box and our Pokemon list. So what
are we gonna do this, we're gonna go and wrap our div in that router, give it that location,
as well as the routes that we just created. And we'll finish off the router. And now we can
take this content section and replace that with the outlet. So whatever the route is, that content
is going to go in here and our nice MX auto kind of put it all together. If you had like a header,
we go above that, if you have like a footer or go below it, all that kind of stuff. All right,
let's go over here. Hit refresh. And there you go. So we can try this out, see if that's
actually the case or not to say div main route. Refresh, cool. We are on the main route.
And currently we're talking in French. That's kind of cool. All right. Okay,
let's get rid of the main route there. And now we want our detail route. So
we want a Pokemon detail component. Here. And where we want to put
that we will put that on a path. Like Pokemon. And then ID and the colon ID means
that anything in the slot here is going to be assigned to a parameter called ID. And there's
a bunch of different things you can put on that. But that's pretty standard way to define routes.
And we'll just point that at the Pokemon detail. All right, and then the last thing you need to
do is we need to make each one of these Pokemon clickable can they currently not? So let's
go back over here. And we'll use that link. Give it the key, say that we're
going to the Pokeyman at that PID. Get rid of this key and then finish off the link. And there we go. So let's see. Okay, hey, now
we got a little finger. Let's click on that. And we have our detail page again in French, but
not really. Okay, cool. Nice. So how do we get the ID from this? Well, we use that use match to get
the ID from the parameter that is ID right here. So we bring in use match, we get the ID,
and then we need to get our list of Pokemon. And then within that, we need to find the Pokemon
that corresponds to that ID. So we do a find. And then we do that parts of the end, I'm
just going to use plus ID there because I like that a little bit better. And
then if we don't have any Pokemon data, we can just say, you know,
no Pokemon found or whatever. Because we already have the data. But if
we do have the data, let's Stringify that. And let's see, we get click on Beedrill. And
nice, now we get our data. Now all we need to do is just format it. So I'm gonna actually bring
in a fairly big block to format this and give us something that you can play with and have some fun
with. Alright, so I'm gonna replace this div with this code, and we'll walk through it. So at the
top, we're gonna have a container div, it's gonna give us a little margin, then we're gonna have a
home link, that's going to link back to slash, so we have a way to get back, then we're gonna have
a two column grid that's going to have the image of the Pokemon, and then over in the other one
will have a bold name. So the Pokemon data here, change that out. Alright, and then we'll have
our stats. And then we go through each one of the stats, so hitpoints, attack events, special
attacks, special defense, all that stuff. And with that, we create a two column grid where we have
the stat name, and then we have the Pokeyman data. So here's a little fun little piece of TypeScript
in here. stat is just going to be a string, HP so and so forth. and Pokemon data is a type object.
So it doesn't know that stat is going to be a key from that type. But we can basically tell it that
it is going to be that by saying that this stat is going to be a key of the type of Pokemon data.
So we're gonna get the type from Pokemon data, which has a Pokemon. And then we're gonna get
a key from that type, and all the keys and that type, our HP attack, and so on and so forth.
And so that's why we don't get any issues with TypeScript right there. Nice, a cool looking
Beedrill, and all of the information about it. Alright, so really, what are we talking
about here, what we're talking about, as an indirect state manager, that in this case,
this react application library is holding the ID of our Pokemon was is essential data to
the function of the page. And so this ID in conjunction with all of the work that we've
done in use Pokeyman gives us an ability to run that detail page and show the Pokemon that the
person is interested in. So it's a combination of our native state management that we've already
built, as well as smartly leveraging third party libraries like React Router, in addition to
replication. And if you're doing lat forms management, I might recommend that you might look
at something like React hook form, or Formic or final form, because all of those will manage the
fields for you. So if you have a big form that has lots of different fields with lots of different
validations, you don't need to manage all the state of the actual form fields themselves, you
can let that third party library do that for you. And I use rakshak form and swear by it. So go
check that out. If you look at the GitHub repo this associated with this video that's linked
to in the description down below, you'll find a direct Pokemon starter folder. And this direct
Pokemon starter is what we're going to use as we experiment with these different state managers.
So what is this? Well, this is a simple starter that we have for this particular application,
I grab the search box, we get the Pokemon list, and all of it is basically sort of unimplemented
and is waiting for us to implement on the store. And the first direct state manager that we are
going to play with is one called sushi Don, it's very popular, and is a unidirectional Data
Manager. So I'm gonna go and clone this direct Pokemon starter and create one called direct
Pokemon to show and, and get started with it. Alright, so I'm gonna go and copy recursively
that direct Pokemon starter to direct Pokemon switched on and then bring it up in VS code. All right, now the first thing I
need to do is install switch donde. And I just gotta I gotta show you the homepage
resist. This is amazing. So this is the sushi Don homepage, it shows you a little bit about how to
use sush. Don, I just love it. Because like it's a bear. It's cool. I just love this page. So well,
whatever. Anyway, so Okay, so there's our zouche on the page. And we can see from it how we create
a Tucson store, we use create. And that's going to give us back our own custom hook that's going
to manage that store for us. And we can use a setter to set it from a method. So let's try it
out. Let's go back over here to our source and in the store. And we'll bring in that create.
And now we're going to create use Pokeyman. So what do we want in our Pokemon
store? Well, we want the Pokemon list, we probably want a list of all the Pokemon in
the store. Because the Pokemon is gonna be like a filtered and sorted version of it, we want a full
list of Pokemon. So we'll call that all Boogeyman. We'll have a way to set the Pokemon.
So that'll be a setter and you give it the Pokemon. And then we also need
the search string, all that search and a way to set that search. Okay, now let's
start this up. So we'll create a Pokemon array, which is just empty, the whole pokimane array is
empty. And we'll set the all Pokeyman function to take a Pokemon array and then
set that all Pokemon to that array. And we'll set search to an empty string,
and then we'll have a setter for a search. So I'm also going to go and set pokimane
here, because I can implant the searching filter and right away but I do want
to have that Pokemon data available. All right, so let's go over to our app and
bring it in. So let's bring in US Pokemon. And then up here, we're going to get
search and set search from use Pokeyman. Now this is one way to do it. Another way to
do it is to use what's called a selector. So here's here's how select It works. So let's say we
want to get search in particular. So we'll use use Pokeyman. And that will get given a function which
gets given the state. And we peel off from that, the search. And I think that's actually the best
way to go. Because what a selector allows you to do is say, Hey, I only want this part of the
store. So only when that store part updates do, I actually want to get updated. And that's a
way to kind of select down from the store. So we have large stores that are being looked
at by a bunch of different components. But the components update on different things. They
should all use selectors. And I think it's just best practice to really start off by using
selectors. So we also got to get set search. And now we can implement on this.
So search is going to go into value. And this is going to call set search. With the
event target value, gotta bring in the event. And Cool. All right, and then down here and
the boogeyman list, we will have our Pokemon. And we will run. Okay, nice. Let's give it a try.
Yarn dev to bring up the server and here we go. So, nothing, so why nothing? Well, we haven't
actually gone and gotten the data yet, but at least it's not blowing up. So that's a
good thing. All right, so let's, uh, let's go and fetch the data, your mind our JSON and then get the JSON from that. And then we're
going to call that set all Pokemon method on that hook. Seems weird, right, but it actually works.
So the first thing we need to do is reference the hook. So use Pokemon. And then we got to get
the state from that that state includes set all Pokemon, and we can use that to set that Pokemon.
So let's try now. All right, cool. So what this is showing us is that you have this externalized
state manager in this Tucson hook us Boogeyman. But you can talk to it outside of a React
component context, which is one of the things that we look for in direct state managers, direct state
managers should be able to be accessed by a unit test, or by code that's external to the React
tree, or code that's internal to the React tree. And that's a sign of a good direct state manager.
And Sushant is a very good direct state manager. Okay, so I think we're doing good. The only
problem is that we don't actually search anything. So we click that and nothing. So let's
go make an admin so so let's go make ourselves a filter and sort function that takes a list of
Pokemon all Pokemon and a search, and then gives us back the list of Pokemon matches that search
also sorted. So we'll call that search and sort. bogeyman, it'll take a list of the Pokemon,
it'll take a search string, and then it will filter through that.
And then sort them by name. But also, we only want to get the
top 10. So let's just slice that off. And there we go. Okay, cool. So
now we have our search and sort. Let's go down here to our set all
Pokemon. And for Pokemon, we can call that set in search, we have Pokemon, but
we also have our search. So where's our search coming from? Well, our search, we gotta go get
that. So we're going to you bring in the GET parameter, and then we'll call get, and
that'll give us the search the current search. So we're gonna do the same
thing down here in search. So we're going to set Pokeyman to be the
search and sort of Pokemon, but in this case, we don't have the pokemon so we need to
go get that but we do have the search. And let's here we go. Perfect.
Love it, and so fast. And you see why people really love swift on it is
a very concise, very easy way to make a new custom hook that manages data for you externally
to the React tree. So you can make it global. But it also integrates really well with your React
app. And also with any other hooks. You could use things like use memo or use state or user research
In conjunction with this, you can have Sushant manage the global data, and then any local data
managed with basic react hooks. So, awesome stuff. So I've talked a little bit about how Tucson
is a uni directional state manager. And that's like Redux. So what is a unidirectional state
manager means well, it means that the data flow in a unidirectional Data Manager only goes in one
way, in order to mutate the store, you have to dispatch a action or call a method on the store
that then changes a store. And because you're subscribed to the store, you then get updated, and
only goes in one direction. The next thing we're gonna look at is Val sheEO. And Val sheEO, is an
example of a bi directional statement, or you can actually just directly set a value and get updated
if that value is updated somewhere else. So it's a bidirectional connection to the state manager. If
you've heard of mob X, Val shield is very similar, just a little bit smaller. Okay, let's go try out
value. Okay, so I've cloned direct Pokemon starter into a new directory called direct Pokemon Val
sheEO, and added Val shield to it. And so let's go over and check out Val sheEO. And see what it's
about. Well, this is the Val sheEO, MPM page. And it shows you that basically, we're creating
a proxy. So our state is held in this proxy, we use a proxy to create that. And then inside of
React, we use the use snapshot hook to connect to that proxy. So in the case of, for example,
a counter, we get the snapshot of the state, so that would include count zero. And then when
we click, we just add on to the count, we just set the value, and automatically, this component will
rerender. Because we know that we also subscribe to count over here, it's just a really nice way
to manage data. Okay, so let's go and create our store based on our proxies and snapshots.
So I'm going to bring in proxy from Bauccio. And we'll create a couple proxies, we'll create
the search proxy by saying we have a proxy and the query string is an empty string. And then we
also have to have a proxy for all of the Pokemon. So far, so good. And now we know we need
to go fetch it. So let's do the fetch work. And then get the JSON back from that. And
then with that Pokemon, we're just going to set that value. That's all we need to do, we
just need to set all Pokeyman Pokeyman. to that. And let's see, so Okay, cool. Let's go
over to our app dot TSX. And bring this in. Alright, so to use our proxies, we need to
use snapshots. So let's bring in new snapshot from value, and that will bring in our proxies
from that store, and now it's gonna get it. So we're going to get a snapshot of the
search proxy, and we'll use that as the value. And then on the change, we'll just set
that value. Search dot query equals the event target value. So use snapshot is really what's
doing the subscription to that proxy. It's connecting that proxy with React, so that when
search changes, this user snapshot, basically fires set some state that state has given back
to us as a snap, and we can then display it. And that's how Bauccio fits into the React rendering
cycle. In order to set it you just go and set the value of the proxy directly. So there's a
little bit of a differential there, you don't want to just call like search that query because
that's not actually going to connect you directly. Okay, so now here with Pokemon list, let's
go and get that all Pokemon and get that. And now down here, we can just take the Pokemon
from that snap, and let's see, are we working? We are, of course, we got crazy
numbers of boogeyman because we've got all the boogeyman in
the list, and we don't search. So how do we fix that? Well, we fix that by
using another utility from vallecito called derive and derive allows us to derive data
from multiple proxies. So let's bring in derive from the utils. And then derive allows us to
create a new proxy. So we'll call that Pokeyman And you give it an object. And then with an
object you give it some call this key list. Now let's do the function that takes and
getter. And then we can use that get her to get other proxies. So we get the search, get
the query from that convert to lowercase, and we get all the Pokemon and then filter it based
on that query. Pretty cool, right? So now, we can get rid of exporting all boogeyman and go back
over here to app dot TSX. Changes to Pokeyman. J that boogeyman and let's see
snapback what we call it again, list. Cool. Hit refresh. Bu lb. Oh, okay. Let's
get on here. Oh, okay. And on to lowercase. Cool. And I think we also slice and
sword right? So let's do the slice. Take the first 10 and then sword. Perfect. Love it. And now we only have a 10.
Great. Awesome. How cool is that? I mean, that is a very, very simple state management
model. When you set a value, you just set it. And then over here, we just do the same thing with
all Pokeyman. We just we just set it up, how cool was that, and then use that snapshot to go
and subscribe to it that's very clean. And then this derive. I love this. So this ability
to just take multiple data sources and derive some data from it dynamically, that is just
great. And it automatically updates anytime that search changes or on clicking on changes,
the thing just automatically re renders. I love that. The another great thing that I love about
state managers like this. And along that line, another model of state management that I'm really
excited about is called atomic state management. And there's three state managers out there
that really define the current state of atomic management, there was the original library recoil
from Facebook, there is the Jo tiny library from dicey carto that she caught Oh, just happen to
also write val, sheEO and soussan. So if you want to subscribe to somebody on Twitter, and learn
all about state, definitely a good follow. And he's also written a great book recently on state
management. So you might want to check that out. And also there is nano stores. So
those three libraries recoil Joe tie, and Anna sores are excellent places to look
when it comes to atomic state management, I'm going to choose to use Joe tie,
and we're gonna go check that out next. All right, so let's take a look at the Joe tie
atomic state management library and how to use it in the list of directories that is in the GitHub
repo associated with this video, there is direct Pokeyman Joe tie. And this is where this code
lives. It's a clone currently of direct Pokemon starter, and we'll just go through it one by
one. So let's go over and look at the store. And this is we're going to start building out
our atoms. So what are we talking about here, let's go over to our Joe type page and see how
this works. So we bring in atom, which is how we define a piece of state and use atom, which is how
we use it in the React context. So for example, you have a text atom that you've created by using
Atom Hello. And then you can have another atom that depends on that atom. So shut when text atom
changes, this uppercase atom will get recomputed to do to uppercase. So again, you're creating
this network of data. If you think about like an Excel spreadsheet, or a Google Sheet, right,
you can imagine text Adam would be a cell, and then uppercase atom would be another
cell that references that original cell. But uppercase is it. And that's one of
the cool things about this atomic state management system is you create this web of
state and just automatically updates itself. And then to interact with it you use use atom,
give it the atom that you want to talk to. And then you get back basically a value and I
set up just like you would with US state. So it's very, very simple. So the first thing we
want to do is bring in that Adam from Joe tie. And let's declare our search, Adam. Fair enough, easy. But how do we get the list
of all the Pokeyman? Well, that's actually a little bit cooler. And I'm going to do it a little
bit differently than I have with the other ones. So we're going to use this Adams with query. And
this allows us to use tans, Dax, query core. So it's basically react query, now connected to a
Jota atom. So let's go and add these libraries and then start the server up again. And then
we import So Adam has a query. And now we just need to create an all Pokemon atom that uses
that Adams a query. So we're saying to Adams a query that we are getting back a, an array of
Pokemon, we give it a function, you give it a query key just like we did with us query before,
where you give it a unique key for your query, in this case, Pokemon. And you give it a function,
just like we did before with us query, now we're giving it that exact same fetch function to go
get that data and that gives us back all Pokemon. And so let's try this out. So we got our search,
and we got our Pokemon, that's probably enough to get started. So let's go over here, app dot TSX.
And bring this in will bring in US Adam from Joe tie. And also bringing us Adam value us Adam
value just subscribes to the value of the Adam. So we'll use Adam the original, which is just
like you stage to go and get the search Adam, because we're going to want to set and
get that. And we use Adam value for the all Pokemon because all we want to do is just
get the value of that. Now let's get our atoms from that store, and then for
the search box, let's use that said the value. And then here
with the event said that search. Good enough. Now with the added
value, we're going to get our Pokemon on the all Pokeyman atom, and we just
display it, hit save, go back over to our display and Bob's your uncle. Nice, but it was
urging. So we need to go and create an atom that looks at both the all Pokemon atom and the
search atom. And when either of those changes, updates itself. So let's go and create a boogeyman
atom that depends on both of those things. So in this case, we give it a function,
that function takes a getter. And with that, we can get the current value of the search item
by just getting a search item, the current value of all Pokemon by getting the all Pokemon and we
just filter. So let's go make this to lowercase. And then we'll use to lowercase in there. And now we've got our Pokemon Adam. So let's
go and get rid of that export because I don't need that and go over to our app and bring
in the Pokemon. Adam, let's call it that. Let's get out of the way. And then down
here. All boogeyman becomes boogeyman Adam. Hit save. Hit refresh. Be you lb
nice. Perfect. Wow, that's cool. You know, I do like this cascade model. And
currently we're just filtering but we also want to slice and we want to sort. So let's create another
atom that depends on pokimane atom that has that. So it takes the existing pokimane
atom. And then it sorts it based on the name, and oh, we also got a slice it. Cool. And now we got to sort of put them on
Adam. And we can go back over here to our app. Bring that in instead. And depend on
that. Let's see. Does it work? Yeah, blast away started out. Okay, you will be cool.
And also is it? Yep, it's trimming down to 10. How cool was that. So now we can see that we have
this cascade of atoms in the store, we've got our search atom, which is basically a simple piece of
text. And then we got our all pokimane atom which is in a synchronous atom that is based on 10 stack
query, it goes off and makes that query and then set itself. And that automatically integrates
with the other atoms such that when it updates, any dependent atoms get updated, which includes
this pokimane atom, which subscribes to both the search atom and also the all pokimane atom
and then returns for its own sake the filtered version of that data. So this is how you derive in
this Joe tie or recoil or nano stores type system. And then we have another atom that listens to
bokeem on atom and so you when you any of these things update, like the search updates, you get
this awesome, automatic cascade. And the thing I really like about it is is that cascade and it is
slightly different from the native react version of that, because we only we kind of have that
in the native react system, right, we've got use date, and use reducer, which are effectively atom.
And then we have use memo, which is basically a way of deriving another atom from the original
atom. The only problem is the based on the nature of React, we have to mend the dependency raise,
notice that we don't have to do that here. By getting the atom, we're automatically subscribing
to it, which is a much, much cleaner way to work. And you don't have to worry about the fact
that you might have dependency arrays that might not have all of the stuff in it that you actually
need. So it removes another potential for error. The next and last direct statement we're
gonna take a look at is the venerable Redux. So I realize getting to Redux at pretty much
the end of the video is kind of like walking a whole marathon and saying, Hey, here's Everest,
it's just a little bit at the end, no big deal. Redux is a huge state management ecosystem.
Essentially, Redux is the longest surviving react state manager, it's been around since the days of
class based components. And probably actually even before that, and I gotta say, it can be a little
daunting. So what we're gonna do is we're gonna use the Redux toolkit to simplify it a little bit.
Redux toolkit gives you a bunch of helpers on top of Redux, that reduces a lot of the boilerplate,
which is a lot of folks, gripes with Redux is that there's a lot of boilerplate. It also has a React
query equivalent built right into it. So that's pretty cool. So we will use that to go and get
our data for us. So this is the Redux toolkit. And I've created our app. Our app is in the direct
Pokemon Redux folder. And it is just a clone of the direct Pokeyman starter as we deal with all
these. Now, this is what we're going to add to the code. We're gonna add Redux, which is the base
library for Redux and react Redux, which is the couplers, basically, between react and Redux,
basically just hooks, and the Redux Toolkit, which as I said, Is this simplifying stuff, simplifying
functions that allow us to really easily create stores and slices. So we'll get into that what
that is in a second. Let me start at the server. And then bring it up, and we got our search box.
Awesome. Okay, so let's go over here to our store. And so what are we gonna do, we're gonna create a
Redux store, and our Redux store is going to have slices in it. So now, when react first started,
the idea was you'd have one ginormous store that would have all of your data in it. And folks got
going rather, hey, that doesn't scale really well, because of having one big store with all the
data in it for the entire application, peoples are running over each other. And so it's nice as
a way to slice the data into parts and pieces so that you can manage it better. So let's bring
in a few imports from Redux toolkit, the first would be create slice, so we're going to create
a slice to hold our search state. So this is just going to be the search me the text string of the
search and also a way to set the search. So we're going to create a slice that slice name, as you
can call search, the initial value, the initial state of this slice is just gonna be a search with
an empty string in it. And then we're gonna have our reducers. So we talked about reducers, when it
came to use reducer, this is a set of functions, each one of which is effectively a reducer. In
this case, we've got a set search, and it takes a state and an action. And the little difference
here with Redux toolkit versus traditional Redux is that in traditional Redux, you would return
a state where that particular value is mutated, but the rest of the were the same, but you return
an entirely new state with all you know, new keys, whereas in this case, Redux toolkit is making it a
little bit easier in that you can just go set the values in the state, and then it does the merging
of your changes with the original state. And it's actually fairly common. And this is actually
fairly controversial in Redux world. And as far as I know, I'm not a huge Redux person, honestly, but
I'm gonna give you the best I got here. So okay. So this search slice has gotten us a lot of stuff.
So let's take a look. So slice has an actions, and a reducer and name. So we're going to
export out of here, the action for a set search coming out of actions. And now we're going
to configure a store that Has that reducer in it. So we're going to use the Configure
store, it's going to give us back a store that we're going to export.
And we're just going to give it that reducer from the search. So that is how we
register each slice into the overall store. Now, if you do store dot get state, which you
can do from anywhere, you can do it externally to Redux, you can do it inside the React tree,
this is all not connected to react right now, you get the state. So that would include search dot
search, because it's the search slice and within that the search value. And so the root state
of this store is the type of the output of get state what it just looked at. So if we do Command
K, Command eye on that, we can see that our root state as he searched slice, and within that the
search value. And then finally, we want to make a selector. So talking about selectors in the in
the case of soussan. Selectors allow you to go and take a store and get out just the data that you
want for the particular component. So we want to create selectors for everything that we need. So
in this case, we're going to create select Search, and that's gonna give us back the selector, the
value for the search current value for the search. Okay, so let's go over to our app dot TSX
and start wiring this up to the search box. So to do that, we bring in a couple things from
react Redux. Now, I mentioned that react Redux are the hooks that connect Redux to react.
So here are the things we need to bring in, we need to bring in a use selector. That's a
hook that given a selector goes and gets the data based on that selector. Use dispatch just
gives you a dispatch function for the current store that you call to dispatch actions just like
we did with use reducer. Use the state and use dispatch use dispatch exactly the same way with
Redux, which is why folks kind of think like, oh, Redux Redux became use reducers.
And it's not that easy. But yeah, yeah, I mean, some of these concepts are very
similar, like, for example, this match. And then the provider and the provider
is a context, you give it a store, and then it provides that store down to
these hooks. So it's bringing that store from the local store. And then let's provide that. I mean, I love how Redux is so, so old, and
has been around for so long, that the provider is literally named provider. It's amazing.
Like other other state management libraries, they have, you know, Redux, or whatever,
you know, library name, provider, whatever, query provider, whatever have you. This one is
just it's provider. It's just provider. You could rename it if you want. But that's what comes
out of library. I think it's the music. Okay, so we got our store. And now we want to go
get use selector to go and get the search value. So we need to bring in that selector
for search. So we need to use that selector. And give it that Select Search. And then we
also need to get a dispatcher. So we just call use dispatch and get our dispatcher. And that just
basically grabs it from the context and brings it in. Okay, so this becomes the value of search and
dispatch, we're going to it's going to dispatch a set search with the event target value. So we
need to bring in event right here. And let's see, actually, let's go and set this to a value for so
foo. See, we've got, Hey, how's that, and it looks like it's working. That's great. So we've got
our slice for the search part of our local store. So now the next thing we want to do is want to
get the Pokeyman JSON. And that means bringing in the query part of reax toolkit. So we're going
to bring in the Create API and the fetch base query functions from the toolkit query. So that's
the query part. And then the React version of the query. So again, with redox, like everything is
sort of, there's the basic, and then there's the React. Okay, so we want to go and do is we want
to build out our create API for our Pokemon JSON. So we do is we invoke that create API, we give it
our path. So pokimane API, we give it the fetch base query. So anytime I say that everything
that we do with this particular API is going to be off of slash. And it's only going to have
one endpoint and that endpoint is get Pokeyman. And that is going to call query with you my JSON.
So we're gonna get basically slash Pokeyman. JSON there. Let's get rid of Yeah, that looks a little
better. Oh, okay. Okay, now let's take a look at what's in pokimane API. So inside pokimane API,
we have our endpoints. Within that we've got get Pokemon. And within that we have our use query,
how cool is that it's automatically created a use query for us. So let's go and actually
export that. So we have our use of inquiry. And we'll just export that. Take a
look over here, bring it in here. And now we can use it. And we'll give it no parameters
because nothing going in. And the output here is either a, an array
bogeyman or undefined. So let's just say that if we have data than once use it. And if we
don't, then we'll use the empty array. All right, not working. Oh, I remember what it was. Okay,
more wiring to be done. Okay, so we've got this pokimane API needed, we'll go bring
this down here and add it as a reducer. Okay, let's take a look. Oh, where it is? Yes,
we have Redux. And it's going I love it. Okay. So now we have, you know, bulb or whatever. Cool. So
let's say that we want to go and trim that down. Well, if you look at the docs, the docs tell you
at this point, if you want to derive some data, one way to do it would just be to integrate this
with an existing tool that allows you to listen to data, and then derive data from that. And
what tools do we have for that? Well, we have good old use memo. So we can use parts of our
existing React Native hook set and integrate them with what we have from Redux, let's
bring in use my mouse and see how this works. So we want to filter and we want to sort the
data based on the search. So let's first get the search right? In that, so we want to
filter and we want to sort the podium on. And it's going to rely on the data as well as the
search. And we're going to return out of this. The data or an empty array, if it exists, because
it might not exist might be known, filtered. by that name, of course, we want to
do our little to lowercase thing. And then we want to slice it. And then we want to sort it. Nice. Okay, so
that'll give us our filtered and sorted bogeyman, or empty array, so we don't have to go check for
any more. Let's hit save and see if it works. So it's giving us 10. That's
great. And let's say you lb noice. Perfect. Okay, so that is one way to do it.
Another way to do it is to actually start the requests for hooking on JSON externally to the
app, and then create a selector over in the store that listens for when that data is done, and
then looks to see if it can take that data from the search and do the same thing, but do it over
on the store side. So we're basically creating a selector that's doing that kind of work for us.
So let's bring in a create selector function. And then we will create a selector. And the first
parameter is to create a selector are a set of functions that select out parts and pieces,
you can have as many as you want, apparently, and the first part gives us our Pokemon. So we're
getting our data from Pokemon API endpoints, get Pokemon select undefined. That's the parameter
that we put in and then the state or the state coming in through deep state and we get the data.
Okay, and then we can go and take this basically, and drop it in here. So we're
gonna take that boogeyman and filter it on that search value. So this
could be undefined. So let's go handle that. All right, cool. So select Pokeyman I like it. So
let's see. Now let's go over here to our app. And instead of using that use memo, we are instead
going to just select out boogeyman based on that slight bogeyman selector Okay, and pokimane Okay, let's give it a try. So nothing to why
is that? Well, we gotten rid of the query that we did, he used to do this use playground
query and give it undefined that initiated the query. So now we have to initiate the query over
here in the store. And the way that we do that is pretty much anywhere, you can do store dot
dispatch, which is again, nice, because you can talk to Redux, both in the React context,
as well as in the external to react context. And then we want to call that pokimane
API with the endpoint of the get Pokeyman, where we initiate it with at undefined. All right,
let's go to try, Hey, okay, now what's happening is externally to react, we are initiating the
fetch of the hook Yvonne JSON here. And then when the store updates, because that get Pokemon
returns a value is then stored in our store. And that store changing then updates any subscribers,
it looks to see what the selector is slightly out, in this case, the selector is looking at the
output of the get Pokeyman, as well as the search and then using the to, to select out a mutated
version of the postman list where we filtered it and sliced it and sorted. So you can use
selectors for more than just selecting data, you can actually mutate the data in the store.
And the selector is actually the right place to do that in this model. Okay, so one more
thing that people love about this is the Redux tools. So if I go here, over here,
Redux, we can see that as I type, we are setting the surge, and you can see all
of the different actions. And this is because I have the Redux Dev Tools installed in my Chrome
and I'm in dev mode. And so that's automatically registered those things together. So that's,
that's, that's pretty cool. So you can see like the, the pending query, you can see the fulfilled
query with the data. It's pretty neat, you know, and you can also do this cool, like, time travel
debugging people will think is really slick, dude. Yeah. Nice. Okay, so there you have it. So Redux.
Of course, all the code is available to you in GitHub in the link in the description below. And
of course, in this, this one is in the direct Pokeyman, Redux directory. Now, before we get to
wrapping all this up, I do want to talk about one more technical thing, check this out. So times
they are changing in React land. And one of the biggest changes has been a recent RFC or request
for comment, that would add first class support for promises to react. And the way that you do
that is kind of different in the client side code, versus the server side code. So on the client
side code, you now have this ability to use a new hook called use that you give it a promise.
And then when that promise is fulfilled, you get the data from that promise, or I
guess you get undefined in the meantime. So let's try this out. Because I think it's worth
knowing about this is not out there 100% Yet, it is in the experimental build of React, as well
as in next Jas 13. So it definitely is coming. There might be some changes between now and when
it actually gets out there. But I think it's worth knowing, because it will fundamentally change how
we do state management in React going forward is adds a lot of new functionality, but also could
replace some existing functionality that we have. So I'll let you be the judge. So let's go over to
the terminal. And we'll do another create V app. And we'll call this one
native use. And you know what, I'm just going to use just basic
react, not TypeScript for this. Bring it up with VS code. And now let's go over
to the package json. And in order to get on to this new experimental build, I need to change
the React and react DOM versions to experimental and then do my yarn and my yarn Dev. And so we now have our app. Cool. All
right. So let's go and try this out. So I'm gonna go create a new file in public
called data dot JSON is going to basically and what we want to do is want to go
get that Add data. So we're gonna go over here to our app dot j SX, and let's
see, get rid of everything basically. So how would we do this before? Well, we do this
before by having some use date, and we'd have a use effect. And we'd use the use effect to get the
fetch, or we could use rack weary and SW are, as we've seen, but now we can do something really
cool. We can basically just create a request here. And what do you say data dot JSON. And
then we'll get the JSON out of that. So now we have this promise just kind of floating
out in space with our data. So let's bring in use. And then we can just get our
data by using that promise. And let's Stringify that and see how it goes. How cool is that? That's really neat. That
being said, you want to see a browser freak out, watch this. So I mean, come on, right? Why
not just go and put that in here. Like that, I mean, it'd be a lot easier to get rid of that.
Hit Save, hit refresh. And now nothing happens. But lots of stuffs happening in our dev tools,
we're going to get in data dot JSON a whole bunch. So why is that? Well, what's happening here?
And let me actually stop our. Alright, so what's happening here is that we run app app then first
starts off a fetch that returns a new promise. And we use that promise, we get the data back
the data started, no, or undefined or whatever. And we put that out. And then finally, this fetch
actually resolves, and we get our data. Use picks up on that, because added to then to it, and it
gets the data and returns a cool that intern re renders app. And you and then we create another
fetch. Now, it's exactly the same fetch. I know, I know, I know, that's frustrating, because it's
exactly the same fetch doing exactly the same thing. But it's a new reference to a new promise
to a new fetch, even though that is doing exactly exactly exactly the same thing. It is a different
promise. So use the end says, Oh, you made a new promise. Cool. All right, I'll go wait for that
one. And so we get is an infinite loop, every data to JSON resolves gets us some data. And it's
so fast, it never even gets to the point where react can actually get enough spare time to put
anything up on the screen. That's why we don't even get anything on the screen, in this case. And
that's why I initially created the promise at the top level here, because that means there only
be the one that one promise that gets resolved. Now we can go back over to our localhost.
And it works. Cool. So there you go. So that's us now on the server side of the house,
it actually is a little bit different again. So we take a look over here at the first class
support, if you look for the server stuff, await in Server components. The idea
now is that you can have a component that is server side rendering only, in
this case called node that can await data, right in the function, you can create
this component asynchronously. This is cool, this is huge. This is something that we never
had before in React is anything function. And react will wait for this function to resolve
because it's a promise, and we can await it. And once it's done, then the server will render
the page and give it out. So this is really cool. And I think there's a lot of potential here. It
certainly is game changing in terms of how it will change state management and react. For the
better for the worse, I don't know. We'll see as next Jas 13 becomes more prominent, but it is very
cool. And it's certainly worth keeping up with. So in summary, let me give you some advice on how
I think you should decide technology choices when it comes to state management in React.
I think first and foremost for local state. You should endeavor to use native state
management, use date, use reducer, use memo use callback. At the point where you
get to use the fact you might want to think about using a third party library, something
like a React query or an SBR because those libraries are going to probably do a better
job. job at managing queries, then you would potentially do building it on your own. Those
are just great libraries, they got re fetching, they've got mutations is fantastic stuff, and
they're definitely going to be leveraged. And I think a combination of native state management,
plus react query and maybe get server side prompts if you're in the next Jas world might be enough
for average applications to manage the state. And then if you have additional needs, in
particular, to allow for global state, so you've got different parts of the React tree, and
you need to get saved from one place to another, then you can either look at doing context,
if you have state that's fairly slow moving, I think that's a good opportunity to move state
around using context. Or you can use something like a Jewish dawn or Joe tie or Bauccio or Redux,
as we've seen, and there are lots of different options in that space. But I think I've shown you
some of the best. Well, I hope you enjoy this. If you have any questions or comments after all
this be sure to put that in the comment section down below. And if you liked the video, hit that
like button. And if you really liked the video, head on over to my channel and subscribe to
it because I do videos well, not this long, but I do good videos, and they come out every
couple weeks or so I think you'll enjoy them. Certainly if you're a React dev it's worth
the subscribe. It's free. See you next time.
Here are all the sections included in this course:
useState
useReducer
useMemo & useCallback
useEffect
useRef
Context and Custom Hooks
React Query & React Location
Zustand
Valtio
Jotai
Redux
The new use hook
Recommendations
Outroduction
Source : https://www.freecodecamp.org/news/how-to-manage-state-in-react/