Hello, friends letās talk about states andĀ
the most common problems you may encounter.Ā Ā Itās one of the most important partsĀ
of React. And after React hooks,Ā Ā it became really easy to handle states we areĀ
just creating a state variable, its set function,Ā Ā and the initial state inside useState hook.Ā
And whenever we want to update the state,Ā Ā we just use this set function and chance theĀ
current state. It looks pretty easy but thereĀ Ā are some important points that we need to know. SoĀ
letās say we have an h1 tag that shows the number.Ā Ā And here, letās create a button and wheneverĀ
we click on this button itās gonna fire thisĀ Ā function and the number will be increased. LetāsĀ
check the app on the right side. Iām clicking andĀ Ā as you can see it works as we expected. But whatĀ
if I add here another button. Again itās gonnaĀ Ā increase the number but this time asynchronously.Ā
Iāll say increaseAsync. Of course, Iām not gonnaĀ Ā create a real async function but we can use aĀ
setTimeout function and will increase this numberĀ Ā after 2 seconds. So when I click, itās gonnaĀ
wait 2 seconds then update the state. Letās try.Ā Ā Now here, and after a while, itās two. It looksĀ
okay. But what if I click on this async buttonĀ Ā and right after that click on the first buttonĀ
a couple of times without waiting 2 seconds.Ā Ā Letās see what's gonna happen. Iām clicking,Ā
Right after that here. As you can see it turnedĀ Ā back to 3. So whatās happening here? WhenĀ
we click on this button our number was 2.Ā Ā Let me take back again. Okey. So when I click,Ā
this number is always remembered. That is becauseĀ Ā here, when we update the state in this way, weĀ
still refer to the old value. So basically, thisĀ Ā number is our reference. To solve this problem,Ā
the only thing we should do is use a functionalĀ Ā update approach. So Iāll say setNumber again butĀ
this time, instead of a value, I'm gonna passĀ Ā a function. And the argument of this functionĀ
will be the latest number we have. LetāsĀ Ā say the previous number or the current number.Ā
Whatever you say but these two are the most commonĀ Ā namings. So you can choose one of them. āpreviousāĀ
or ācurrentā. And I'm gonna take this numberĀ Ā and increase here like that. Basically, we are notĀ
re-creating our number. We are just updating theĀ Ā current value in the memory. Letās see right now.Ā
Increase, async, increase again a couple of times.Ā Ā And as you can see, it works as we expected.Ā
So when you update your state itās betterĀ Ā to use the function version insteadĀ
of updating it directly like that.Ā Ā Okey. The second common useStateĀ
problem is the initialization.Ā Ā When you initialize your state, what youĀ
are writing in useState is really important.Ā Ā Let me show you what I mean.Ā
Iām creating a user state.Ā Ā And at the beginning, we donāt have any user.Ā
Itās gonna be empty. But letās say we are gonnaĀ Ā fetch a user data later and update this user. AndĀ
after updating Iām expecting a user like username,Ā Ā email, and images array which includesĀ
the profile picture and the cover picture.Ā Ā Something like that. But remember we donātĀ
have them yet. So if I come here and say,Ā Ā username is user.name. Letās save. AsĀ
you can see there is a white screen here.Ā Ā And itās a really common problem, I saw this manyĀ
times in lama dev social media groups. People areĀ Ā having trouble with this blank page issue allĀ
the time. By the way, the group links will beĀ Ā in the description below if you want to join andĀ
ask your questions. Anyway, the problem is ourĀ Ā user variable is undefined. We didnāt provide anyĀ
type here. But in the html section, we are tryingĀ Ā to get an object property which we donāt haveĀ
yet. To solve this problem we have many options.Ā Ā The first one, you can write here a conditionĀ
and say if there is a user show me this span.Ā Ā In this case, only after updating the user, weāllĀ
be able to see its name. And the second solutionĀ Ā is writing here a question mark. Basically itās aĀ
shortcut to verifying an object or array. I meanĀ Ā itās the same thing with writing here if thereĀ
is a user show me user.name. Letās take it back.Ā Ā And the last solution is to initialize your statesĀ
with the expected type. So if itās gonna be aĀ Ā string just write here an empty string, if itās anĀ
array write an empty array. And in our case, itāsĀ Ā gonna be an object. Right now there is no blankĀ
page anymore. But sometimes itās not enough toĀ Ā write only an empty object here. For example, ifĀ
I write one more span, and say profile picture isĀ Ā user.pictures and Iāll take the first picture inĀ
this array. So if you look at the app again youĀ Ā see that we have exactly the same problem. That isĀ
because this time we donāt have such an array. ToĀ Ā prevent this, you can write here what propertiesĀ
you exactly need. Like username, string, email,Ā Ā string, and images, array. In this case, we wonātĀ
have any problem. I highly recommend you to writeĀ Ā them like that because most probably you are gonnaĀ
forget writing a condition somewhere in the html.Ā Ā So donāt forget writing your types. Okey. RightĀ
now, Iām gonna change the initial state and IāllĀ Ā give a name, email, and images. So what I wantĀ
to do is to update the only name of this user.Ā Ā To do that Iām gonna create anĀ
input which takes a username.Ā Ā And a button to update our user. And IāllĀ
create another state that holds an empty string.Ā Ā So whenever I write here anything itās gonnaĀ
update this input state. To do that Iāll createĀ Ā an onChange event, and update the input like that.Ā
Basically, the target of the event is this input,Ā Ā and value is the string that we write here.Ā
Okey, we have a name right now but how Iām gonnaĀ Ā update this user? Remember Iāll change only thisĀ
username, all other properties will be the same.Ā Ā Letās write here a clickĀ
event and call a function.Ā Ā changeUser. Letās create this function. WeĀ
already know that we shouldnāt do this by writingĀ Ā user.name=input or setUser(user.name=input).Ā
Itās not gonna work because we are not returningĀ Ā a user here. Inside of the set method shouldĀ
be a user object. Itās gonna assign this valueĀ Ā to user state directly. What I mean by that?Ā
Iāll say console.log and user. I'll change hereĀ Ā and click. And as you can seeĀ
it returns directly this stringĀ Ā and the user is not an object anymore.Ā
It removed name, email, and image.Ā Ā You might think to write here an updatingĀ
function and write it like that. But again,Ā Ā we are not returning any object. Itās gonnaĀ
return only this value. Letās see. As you can seeĀ Ā still the same. So what we should do is toĀ
update this name property while returningĀ Ā the user object. You are gonna understand what IĀ
mean better right now. Iāll say return an object.Ā Ā And this object will include everything in theĀ
current state, name: john, email:john@gmail.com,Ā Ā and images everything will be the same. But IāllĀ
update only name here. it will be the input.Ā Ā And right now, when I click itāll update onlyĀ
username. If you donāt know using this spreadĀ Ā operator let me explain quickly. Let's say weĀ
have an object which includes name, surname,Ā Ā and age. If I define another object. And itāllĀ
take every properties of this object. And as youĀ Ā can see it's exactly the same. Iāll say takeĀ
everything but additionally add here a city.Ā Ā And right now it has name surname age andĀ
city. And also I can change any property here,Ā Ā as we did in the example. let's sayĀ
take everything but change the surname.Ā Ā Okey, I think you understood how it works.Ā Ā And this usage is really useful especially whenĀ
you have a form and you have many inputs inside.Ā Ā Let me create one. Actually, Iāll just copyĀ
and paste. As you can see, I have 8 inputs.Ā Ā And the biggest mistake you can do is to createĀ
here useState hooks for each input. For name,Ā Ā for surname, for every single one. It consumes aĀ
lot of time and it reduces the code readability.Ā Ā So what you should do is to create aĀ
single useState which includes everyĀ Ā properties. And change their values usingĀ
only one function. So Iāll grab my inputsĀ Ā and create a change event. OnChange handle change.Ā
Letās create this function. Iāll do exactly theĀ Ā same thing. Iāll use the functional update,Ā
take every properties from the previous state,Ā Ā and change a specific property according to eventĀ
target. For example, if I change here itās gonnaĀ Ā update only name. But how Itās gonna know whichĀ
input I'm in? For user it should write here:Ā Ā name: e.target.value, for surname: surname,Ā
e.target.value. Basically we are gonna needĀ Ā their names. Itās really easy to handle that. IāllĀ
choose again all of these inputs. And give themĀ Ā some specific names. Itās gonna be name, surname,Ā
and others. But make sure that these names areĀ Ā exactly the same names in the state object. RightĀ
now I can use those names like that. Donāt forgetĀ Ā this parenthesis itās a property name. IāllĀ
write a console log and check my state. And now,Ā Ā doesnāt matter which inputs Iām writing in, itĀ
directly updates my state. Itās really useful whenĀ Ā you want to update multiple states. But should weĀ
use useState hook everywhere that we need a stateĀ Ā or states. The answer is no. Sometimes usingĀ
a useReducer hook is much better than usingĀ Ā a useState. Of course, there is no rule that youĀ
should use usereducer instead of usestate or itāsĀ Ā not a mistake if you use it. But in some specificĀ
situations, useReducer is more advantageous.Ā Ā For example, if you have a more complex objectĀ
that has different properties like arrays,Ā Ā nested objects, and other things here itās betterĀ
to use a reducer because when you update differentĀ Ā properties, itās gonna be really messy here.Ā
Because all elements here are not strings orĀ Ā numbers like in the previous example. SoĀ
we cannot update them in one function.Ā Ā We have tags, we should separate each tag and pushĀ
inside this array, or choose different categories,Ā Ā increase or decrease this number, and there isĀ
a nested image here. Actually, this example isā¦Ā Ā okey, but can you imagine you have maybe 10, maybeĀ
more properties here and youāll have to use spreadĀ Ā operator all the time and, probably youāll makeĀ
a lot of mistakes. So creating a useReducer andĀ Ā using different actions for each changes might beĀ
more useful here. Of course, Iām not gonna deepĀ Ā dive into useReducer in this tutorial but if wantĀ
to see in the future let me know in the comments.Ā Ā And the last common mistake is to derive statesĀ
incorrectly. Let me explain. As you can see weĀ Ā have products state which includes id title andĀ
quantity. And we are listing all these productsĀ Ā using a map here. Itās title and there is aĀ
quantity and it includes its number and twoĀ Ā buttons here that we can increase or decrease thisĀ
number. As you can see we are passing the productĀ Ā id, and in the function, we map throughĀ
all products and find the related productĀ Ā and increase its number. You already know howĀ
we do this. Letās see, it works perfectly.Ā Ā And here we have a select button. When we clickĀ
on this button, it fires this select functionĀ Ā and basically, it takes the product id andĀ
finds the product that we want, accordingĀ Ā to this id. And after finding, it sets a newĀ
selected product. And we show this product here.Ā Ā Everything looks nice, we can select any productĀ
here. But the problem is happening when we tryĀ Ā to update product quantity. As you can see weĀ
increase this number but the selected product isĀ Ā still the same. That because the product insideĀ
the selected state and the product inside thisĀ Ā array are not the same. We just created hereĀ
a new product. We are not exactly choosing itĀ Ā from the array. So how we can solve this problem.Ā
Basically, instead of storing here a new product,Ā Ā I can store only its id. So when I selectĀ
any product Iām just gonna update selectedId.Ā Ā Now I can write here selectedProduct. AndĀ
again weāll find the product using its id.Ā Ā Letās try. Iāll select this product. And when IĀ
increase this number it increases here also. AndĀ Ā itās really important guys. Especially if youĀ
are not working with a state management tool,Ā Ā youāll encounter this issue all the time. SoĀ
donāt forget, if one state affects anotherĀ Ā state just store its id, instead of creating a newĀ
object inside. Okay, I can give more examples butĀ Ā those are the most common problems that you willĀ
most probably have in the future. But right nowĀ Ā you know how to handle them. I hope you likedĀ
it. If want to learn any other react hooksĀ Ā like useEffect, useMemo, useCallback or anyĀ
others just let me know in the comments. IfĀ Ā you learn sth new today please like the video.Ā
I hope Iāll see you in the next video. Goodbye.
I can see the pretty rough graphic design mistake that is your thumbnail š
2 and 3 can be summarized as "use typescript"
1 common mistake every beginner makes :
I just want to say thank you for posting this. I've been stuck on an issue for a couple of days and didn't even know what to google to solve the issue, and this helped me figure out what the issue is.