Every Beginner React Developer Makes This Mistake With State

  Рет қаралды 214,104

Web Dev Simplified

Web Dev Simplified

Күн бұрын

FREE React Hooks Course: courses.webdevsimplified.com/...
By far one of the biggest beginner React mistakes I see is developers storing derived state. This is a huge problem that is incredibly hard to detect unless you know what you are looking for. In this video I will show you what the signs are of derived state so you can make sure you never store derived state.
📚 Materials/References:
FREE React Hooks Course: courses.webdevsimplified.com/...
Derived State Blog Article: blog.webdevsimplified.com/201...
🌎 Find Me Here:
My Blog: blog.webdevsimplified.com
My Courses: courses.webdevsimplified.com
Patreon: / webdevsimplified
Twitter: / devsimplified
Discord: / discord
GitHub: github.com/WebDevSimplified
CodePen: codepen.io/WebDevSimplified
⏱️ Timestamps:
00:00 - Introduction
00:48 - Derived state problem
02:45 - How to fix the problem
04:26 - Performance considerations
#React #WDS #useState

Пікірлер: 236
@cmlttnts4906
@cmlttnts4906 Жыл бұрын
I wouldn't call this example a "derived state example". This is two different states having a relationship. Derived state means a value that is directly calculatable from other states. Selected user cannot be calculated from other states (users), it simply requires a user input ( outside event). This is still a good example of "states with relationship, should be updated together" example.
@PavanMehta
@PavanMehta Жыл бұрын
I agree with you.
@robertsandiford6223
@robertsandiford6223 Жыл бұрын
It's essentially the data normalisation problem from relational databases. Don't store the same data in 2 places or risk inconsistencies. Instead store a reference to a single location.
@cmlttnts4906
@cmlttnts4906 Жыл бұрын
@@robertsandiford6223 Yes. But in database layer, there is a guarantee of unique ID. For frontend, you don't always have that. Assume that "id" doesn't exist, or every field can change. For example, next to the "Increment" button, we have a text input, which changes the "id". Now, we have the same initial bug. The ultimate solution is to update them both at the event handler ( or use something with reducer, which does the necessary updates in one place through an action). I would give a "derived state" example like this. Assume there are 2 inputs, one is "firstName", the other one is "secondName". And you hold the "fullName" in state. "fullName" is fully derivable from "firstName" and "secondName". It doesn't need to be stored as state. It should just be calculated whereever you need.
@mrhenry60412
@mrhenry60412 Жыл бұрын
@@cmlttnts4906 Thanks for your sharing . That’s really helpful and clear.
@robertsandiford6223
@robertsandiford6223 Жыл бұрын
@@cmlttnts4906 IDs are not guaranteed in databases, it's a design choice to add them. Generally you can choose to ID your state data if you want to. You can do parallel updates in event handlers, and that is fine for simple tasks. It's not recommended in large DBs because of the risk of making a mistake - in a simple component it would be ok, but might cause trouble if complexity grows. You example with first name and last name matches database normalisation principles - the fields are the single store and value, and they are referenced to build to composite value when required, the same as selecting from multiple tables in relational databases.
@jinggong4033
@jinggong4033 Жыл бұрын
my app works just fine coz I put the selectedID in the dependency array of the useEffect where I fetch API and set the state.... but now I see how silly my solution is while I can just use your simple one line of code to define selected state.....changed it immediately! thank you!!!
@DanN-no1qk
@DanN-no1qk Жыл бұрын
Great videos man thanks for all your effort!
@kllokoq
@kllokoq Жыл бұрын
Beautiful explanation!
@19JB90
@19JB90 Жыл бұрын
Nice Vid. Still happens in my code a lot. Great to have this explained and simplefied :)
@user-uw5dv5el8m
@user-uw5dv5el8m Жыл бұрын
Great video, very helpful !!
@poushalibhattacharjee2166
@poushalibhattacharjee2166 Жыл бұрын
Thank you for this tutorial. It helped me understand the concept. Waiting for more such videos on React. A request if you could tutorial on react testing like Jest and React Testing Library
@chengxiaoxia8046
@chengxiaoxia8046 Жыл бұрын
I like Kyle's tutorial course. You explain the concepts clearly and make the courses comprehensive. You share the knowledge, the keys to write simple and high-quality code without reservation. I bought some online React and css courses. I think Kyle's course is worth the price. Thanks.
@samyogdhital
@samyogdhital Жыл бұрын
amazing video, will definitely keep in mind from next time.
@benjadiaz6475
@benjadiaz6475 Жыл бұрын
Excellent video, just the explanation I needed. Thank you very much for the video
@yanhuan1
@yanhuan1 Жыл бұрын
I think derived state doesn't need to use the useState at all, it should be calculated based on users state. So I'm not sure is this a truely example of derived state.
@huseynfy
@huseynfy Жыл бұрын
Thanks for another great video!
@theophilus494
@theophilus494 Жыл бұрын
Awesome 👍... Thanks so much
@kushagra4401
@kushagra4401 Жыл бұрын
Thanks a ton for sharing all this valuable info and experience with us. U are a gem for students like me
@hardwired89
@hardwired89 Жыл бұрын
Thank you for this content 😭😭😭👍
@godwinjohn7564
@godwinjohn7564 Жыл бұрын
Thanks so much 🙏 I just removed unnecessary code and increase performance in my project
@andriiauziak1178
@andriiauziak1178 Жыл бұрын
Honestly Kyle, I was going to read the article, I think so... So thanks a lot for the video version))
@krishgarg2806
@krishgarg2806 Жыл бұрын
Thanks. This is a pretty common but annoying possible bug. This is another reason why I love svelte so much, just use $: and it becomes reactive, derived or whatever you want.
@22afabio
@22afabio Жыл бұрын
Great lesson! This is a source of many bugs... I've tried solving it in another way (as a practice). My goal was to fix the bug and improve performance, and this is what I came up with. export default function UserLop() { const [users, setUsers] = useState([ { id: 1, name: "Kyle", age: 27 }, { id: 2, name: "Sally", age: 32 }, { id: 3, name: "Mike", age: 54 }, { id: 4, name: "Jim", age: 16 }, ]); const [selectedUserIndex, setSelectedUserIndex] = useState(); function incrementUserAge(id) { setUsers((currUsers) => { return currUsers.map((user) => { if (user.id === id) { return { ...user, age: user.age + 1 }; } return user; }); }); } return ( Select User:{" "} {selectedUserIndex == null ? "None" : `${users[selectedUserIndex].name} is ${users[selectedUserIndex].age} years old`} {users.map((user, index) => { return ( {user.name} is {user.age} years old.{" "} { incrementUserAge(user.id); }} > Happy birthday {" "} { setSelectedUserIndex(index); }} > Select ); })} ); } What do you think?
@k0si
@k0si Жыл бұрын
this will bug out if you have a dynamic list, as objects under indexes can change
@hd33444
@hd33444 Жыл бұрын
@@k0si hey man, would you be able to explain what you mean by that some more??
@k0si
@k0si Жыл бұрын
@@hd33444 Well lets say you have 3 item list. So indexes from 0 to 2. Select 2nd item, so index = 1, thats in state now. Now if you would have an option to delete items, you could delete 1st item, and your currently selected item, previously with index == 1, now actually has index == 0 (its the 1st element now). But in your state there would still be, that selected index is index = 1. However, now that would actually be referencing the previously 3rd item in the list. In general using indexes to point to elements in the array is not such a great idea if you have dynamic lists (using .map and its 'index' argument as 'key' prop as well) In my experience i found that just having the objects with 'id' key/value and referencing those is the most simple and reliable way to identify them in the list ;)
@hd33444
@hd33444 Жыл бұрын
@@k0si Ahhh ok yeah that makes sense. Thanks for the answer!
@AndresGomez-sv7th
@AndresGomez-sv7th Жыл бұрын
Nice video, but I have a question, if always change user list, useMemo is worth?, because it added a validation to change its value and always values change, I prefer to acces with index but it not always work
@wallghing
@wallghing Жыл бұрын
You actually "break" the reference to that object when you do return { ...user, etc }, this creates a new object with the same contents, therefore: new reference. You should apply the increment directly to user and return user to keep it working straight. But if you work with references you open up to a lot of problems if you dont really comprehend how references work. Unless you dominate or are trying to dominate references, use native values to avoid issues.
@HobaiRiku
@HobaiRiku Жыл бұрын
indeed
@uriniumintestor7302
@uriniumintestor7302 Жыл бұрын
Yeah mutating the original user object would be the best fix here
@zsoltoroszlany7172
@zsoltoroszlany7172 Жыл бұрын
I'm not a React expert yet it caught my eyes too, it was strange but I told myself I just made up. Nevertheless I guess I my intuition was right.
@marios594
@marios594 Жыл бұрын
what are you talking about? You cant mutate states
@HobaiRiku
@HobaiRiku Жыл бұрын
@@marios594 I think he can, mutating value directly of the item in the array does the same thing, but in React.StrictMode, state updater will run twice. we can get rid of strict mode or use state value (directly from users and set it like [ ...users ]) instead of state updater. still, I'm not familiar with react and I don't know if this is the appropriate way.
@BHFJohnny
@BHFJohnny Жыл бұрын
Yep I like Vue approach more. Computed props are more straightforward there. In React, I do it this way as you showed. useMemos everywhere.
@Undef1Gned
@Undef1Gned Жыл бұрын
If you have a list of items that doesn't change as often, you could simply save the index of the item in your array. So you don't have to loop through the array to find the correct item
@black_platypus
@black_platypus Жыл бұрын
Yes, the structure here isn't optimal in general. With the IDs, which should be unique, simply being a property within the objects within an array, as opposed to being the indices or keys in an array or object, we're also missing out on directly addressing them. I wonder if that's common practice if you're just pulling objects from your DB?
@fabienbroquard7690
@fabienbroquard7690 Жыл бұрын
Even if the array changes often.. Just using a setSelectedIndex in his selectUser, that's where the find has to be done (as findIndex()), once only when the id changes.. And set to 0 when the usersArray changes to not have a wrong index (or again find the id in the new array). This saves the overhead of useMemo too ;)
@esemelekete1330
@esemelekete1330 Жыл бұрын
I agree. Accesing a map/array element with index is absolutely quicker than looping through a list of element.
@karansamra
@karansamra Жыл бұрын
Why did you pass reference type variable as a dependency to use Memo It will change on every render and useMemo will just become inefficient
@nro337
@nro337 Жыл бұрын
Really great video, valuable to understand. Thanks!
@FreedomForKashmir
@FreedomForKashmir Жыл бұрын
What's the best to chose among useCallback() and useMemo() ?
@bernardus3289
@bernardus3289 Жыл бұрын
Oh wow I thought after a week or 2 of learning react, I got the hang if it but man did I find this video hard to keep track of
@whizzninja9740
@whizzninja9740 Жыл бұрын
Excellent!
@orlandofury
@orlandofury Жыл бұрын
Sorry maybe some here asked the same question, how is the name of the extension you are using to show the error in that big modal in the app instead of going to the console??? please a link to it or the name to search it please?
@tejasnikam3287
@tejasnikam3287 Жыл бұрын
Awesome 👍👍
@dave6012
@dave6012 Жыл бұрын
Nicely done. It would be all too easy to try to useEffect to keep state values in sync, and you dodged that pitfall like a baus.
@yusufkaraaslan2888
@yusufkaraaslan2888 Жыл бұрын
Thanks !
@shahidshafi1227
@shahidshafi1227 Жыл бұрын
I encountered exact same problem few days ago 😄.
@stoncjoesperanto8632
@stoncjoesperanto8632 Жыл бұрын
@Kyle The code is still a little too small to read properly on a phone (tho you have the space in x). Thanks for your videos
@baileysli6235
@baileysli6235 Жыл бұрын
3:02 - Try to press `F2` for renaming const in whole document. It really helpful sometimes.
@ujjvalw2684
@ujjvalw2684 Жыл бұрын
These small tips come from experience. I don't have any 😭
@BarberoPablo
@BarberoPablo Жыл бұрын
Really good explanation and short video, thanks!
@ElrondMcBong86
@ElrondMcBong86 Жыл бұрын
In all this code/ video there ain't any database-calls / redux used, right? I wonder, if/how I can use this, if I have to use database calls.. :-S
@Stubbelur
@Stubbelur Жыл бұрын
Wouldn't it be more performance to pass users.length into the useMemo dependancy array?
@caesarbala
@caesarbala Жыл бұрын
i used useEffect instead of useMemo is there any downside on this approach ?
@KathouQC
@KathouQC Жыл бұрын
Great video, one thing I would say about react hook: I just love it! Before I used to use react use state but once I know how hook work, it's just so much better :)
@mohithguptakorangi1766
@mohithguptakorangi1766 Жыл бұрын
Can't we use Useref() hook to refer to that selected user?
@gerasTheMessiah
@gerasTheMessiah Жыл бұрын
When he uses the "users" array to keep track of changes with the useMemo() call.... 1. What is react checking exactly behind the scenes? Just the pointer to the array "users" or a more deep comparison (things like length, changing the objects (per se or sub-properties) inside each index, etc) ? 2. Also isn't "users" being re-created on each render cycle? Wouldn't useMemo going to be doing the find() operation every single time?
@jmg9509
@jmg9509 Жыл бұрын
LMAO I kid you not I was just learning about this in the Scrimba React course. What a coincidink that this would be uploaded only a couple hours prior, and show up as the first thing on my youtube feed.
@abskawser8565
@abskawser8565 Жыл бұрын
What is the Jackson model that?
@lucappelman8558
@lucappelman8558 Жыл бұрын
Now I wonder if I ever did this. It seems like a obvious mistake, but of course it can get you in some weird troubles.
@TheTenThousandThings
@TheTenThousandThings Жыл бұрын
bravo!
@thecutedreamkostasp.4449
@thecutedreamkostasp.4449 Жыл бұрын
Why dont make an extra selectedUser field in the users state ,and when u update user age u update age of user on users array and the age of selectedUser the same time.
@willyhorizont8672
@willyhorizont8672 Жыл бұрын
Thanks
@malikbhai2285
@malikbhai2285 Жыл бұрын
Dear Bro, me install just react version newly but take some problems,, when i use input tag then page show me only "Blank Page" plz help me.... i working last 5 days but no any solution...plz make video not show me blank page..me waiting your video. i am from pakistan
@rahulnag9582
@rahulnag9582 Жыл бұрын
If we can store the array position in selectedUser state and on update of user in useEffect we can use this array position like user[selectedUser] then it will be far easier and faster compilation of code
@kashug.
@kashug. Жыл бұрын
but also more prune to bugs, to get a negligable performance gain unless you have a wierd case. Usually react does not re-render that often so the linear-search is not done very often and in most cases the list is short enough to not matter anyway. And in those rare cases a useMemo is probably fast enough and less prune to you making bugs. (if you store the index you need to be 100% sure the list never changes - and what if we added features for add and delete users later? - you would then have to make sure that you also update the index on those operations. Easy to forget, and would trigger a bug.
@smaranh
@smaranh Жыл бұрын
Do you have a Redux course?
@doc8527
@doc8527 Жыл бұрын
Just copy my reply to comment so new devs might be aware of. There are few problems with the video example and solution. For the example itself, check the top comments with highest vote regarding the definition of derived state. I want to point out the problems with that solutions from some of the comments and the video, the video example is really tricky. First, some of comments say use array index so you don't need to use array.find(), it's questionable/wrong to use array index id as selectedUserId cuz the array index will cause bug once the array size changed hence index is not longer unique. If u pretty sure the size and position are static under any circumstances. This approach is probably the most performant and simplest solution Second, use the unique user id as the find id. This is the video solution, it's good but when the size is large, it will cause performance issue as the video claimed later. However, the useMemo() in this case, doesn't solve the performance issue because when you update the selection, it will modify the array hence cause useMemo() to rerun. the useMemo will be useful only when the parent container is changed but at the same time you don't want to re-render the current selection list. But for this example with its context, the useMemo() solution is simply wrong. the trouble array.find() will still run regarless. So what's my answer? I would say if the list is large, the performance is important, the initial code is fine. You just need to update both selectedUser & users when you call the update, and only update selectedUser if the user id is matching the updated user in users list. You don't even need to use the array.find() and useMemo() in the first place, it also reduces the mental overhead of using memo hooks. The root issue of his solution is because the "issue" example he provided doesn't match the definition of derived state. It just looks like it, that's why I called it tricky. If the example is derived state, you shouldn't need useMemo() most likely.
@freshlix9554
@freshlix9554 Жыл бұрын
Very important lesson in your software class.. but who in the interpreted react/js world cares about storage? As far as I know it's always important to keep redundancy low, but it's not always the best tradeoff. At some degree of complexity for a specific calculation you should avoid recalculating specific values time over time, rather than just looking them up in the storage. If your use case isn't time-sensitive as it is the case for most basic applications I usually limit this to a depth of 42 additional operations in comparison to a simple lookup in storage, it's ideomatic just for simplicity and to have this as a reminder if time matters 😅 especially in the SQL area with less 'intelligent' DBMS systems - often found in cluster cases - this helps out to improve the timing overall. Most of the time I would recommend using higher structures represented in arrays or maps/objects to keep track of changes more granularly, but that's case specific, as every decision you make in your life.
@freshlix9554
@freshlix9554 Жыл бұрын
But oops, watch out for mutants! 👾
@iam_ck
@iam_ck Жыл бұрын
I think states having relationship with each other should be treated with useReducer.. as you need an single state but multiple ways to update it...
@Mickey_McD
@Mickey_McD Жыл бұрын
Instead of useMemo maybe put the users in a Map using the ID as the key, or maybe save the array index of the selected user in the state rather than the ID.
@ivanche8051
@ivanche8051 Жыл бұрын
why not useMemo? That’s what it’s made for
@gordonsau2989
@gordonsau2989 Жыл бұрын
@@ivanche8051 useMemo can only memorize if the function has already run once. If we select another user that has never been selected, we still have to go through the whole list of users to find the id. Using id as key in this case can search quicker.
@jethya3640
@jethya3640 Жыл бұрын
Is your course worth it in 2022 react js?
@akrembc7951
@akrembc7951 Жыл бұрын
what he didn't explain is WHY "selectedUser" and the user that its age is incremented are not the same reference? the reason is that when incrementing one user's age we mutate that user it by destructuring .. so we're basically creating a new one : return { ...user, age: user.age + 1 }
@alecodes
@alecodes Жыл бұрын
It's because the user's state is copied into selectedUser, so they have nothing to do with each other
@ricardoamendoeira3800
@ricardoamendoeira3800 Жыл бұрын
Thanks, I was wondering why he didn't address that. Sharing the reference would be a simple fix, although it also has its own downsides.
@uriniumintestor7302
@uriniumintestor7302 Жыл бұрын
@@alecodes no, it’s not copied. SelectedUser references the same exact object which exists in the array of users. The problem is in Increment function, where he replaces the object in the array with a new object. If he just mutated the original object on age increment, everything would work fine, and I’d actually like this solution more.
@feritperliare2890
@feritperliare2890 Жыл бұрын
@@uriniumintestor7302 ah but you can't mutate it like that in react cause react is written by crazy people
@uriniumintestor7302
@uriniumintestor7302 Жыл бұрын
@@feritperliare2890 I don’t see why not. They use “setState” to set the result state again. Why do you think it wouldn’t work?
@Matyanson
@Matyanson Жыл бұрын
What if I use useEffect instead?
@elitracy1784
@elitracy1784 Жыл бұрын
Why not just use the users variable as a dependency in use effect and update selected user in use effect?
@koksikskkj7937
@koksikskkj7937 Жыл бұрын
Emmm if we know, when the current age is increment, cant we then update current user? incerementAge -> ...changing data in users... -> set current user by inceremening with new date
@acabreragnz
@acabreragnz Жыл бұрын
It's dificcult to manage the syncronation, specially when you have lots of states. Keep it simple :)
@amitneuhaus2989
@amitneuhaus2989 Жыл бұрын
If users list was huge, isn't it inefficient to filter through them? I would suggest saving the users as object with keys as ids, and then getting the selected user is o(1)
@arjobansingh1940
@arjobansingh1940 Жыл бұрын
That is also good solution, but then to render users, you have to create array from an Object which would also be O(N) on each render. Or again we could useMemo on that object and create new array from that object only when users change. But again, we are down to same thing, either we have create array from users object or that filter derived state. I guess filter derived state would be faster, as filtering can not always be in worst case, sometimes we can find user ar first place only, and it’s average case would be finding user in mid of an array. But on other hand we have to create whole array from Object with Object.keys, values or entries function etc. Which is always exactly O(N).
@ElektrykFlaaj
@ElektrykFlaaj Жыл бұрын
if the list is huge then the list should get shorter. You can add pagination of some kind
@amitneuhaus2989
@amitneuhaus2989 Жыл бұрын
Good argument,. you can have list of ids which can represent the order of rendering, and objects of items in object with id as keys. Rendering list through the ids array, selecting the object from the objects state.
@amitneuhaus2989
@amitneuhaus2989 Жыл бұрын
@@ElektrykFlaaj yeah but when you add pagination and don't have all the data on the UI you lose alot of abilities, like searching on the frontend, and you'll have to do backend search and sort..
@arjobansingh1940
@arjobansingh1940 Жыл бұрын
@@amitneuhaus2989 yes I guess, depends on use case. If users aren’t going to change much rather selected user would, than using object as initial state in fine, considering we are memoizing the render array with useMemo. Otherwise, if users data is getting changed often, we can use this array approach shown in the video.
@divinsmathew
@divinsmathew Жыл бұрын
Why not simply use useEffect to update selected user with users in dependency array?
@ElektrykFlaaj
@ElektrykFlaaj Жыл бұрын
because it's not "simply", you're increasing complexity and decreasing readability. in general if it's not necessary to store something in state then you probably shouldn't store it in state
@andy-ally
@andy-ally Жыл бұрын
useEffect will run after render. It is used for side effects.
@ujjvalw2684
@ujjvalw2684 Жыл бұрын
@@andy-ally constructive
@christofferhammarstrom
@christofferhammarstrom Жыл бұрын
Doesn't using useMemo like this reintroduce the bug where the age is not incremented for the selected user?
@adarshs4871
@adarshs4871 Жыл бұрын
No , useMemo is just used for optimization it has nothing to do with the logic
@christofferhammarstrom
@christofferhammarstrom Жыл бұрын
@@adarshs4871 I mean the number is still incremented, but because of useMemo it will not be shown as incrementing in the UI.
@ioannispotouridis297
@ioannispotouridis297 Жыл бұрын
To go a step further into performance, I'd keep the users state as an object instead, where key is the id and value is the user, so your derived selectedUser state wouldn't have to loop (find) throught the users array every time selectedUserId changed, but actually access it directly e.g. const selectedUser = useMemo(() => users[selectedUserId], [selectedUserId, users]);
@Robula
@Robula Жыл бұрын
Seems like a perfect candidate for a Map.
@alvin6088
@alvin6088 Жыл бұрын
how about using `useRef`?
@rohan1765
@rohan1765 Жыл бұрын
Can anyone help me to understand, After memorizing the function to derive selected user Kyle said that, It will help to boost performance if there are bunch of other states - which makes sense, But he also said that if we have 1000s of users it will help with performance, If users are in dependacy array, meaning that function is going to run and iterate through every user any time user's value change, how would it help here?
@mateuszwojciechowski495
@mateuszwojciechowski495 Жыл бұрын
without memoizing, every time you click "increment" the 'selectedUser" function would run each time. With useMemo, only when you click "select" the function will run, thus running only when you need it to, and not whenever the component rerenders
@rohan1765
@rohan1765 Жыл бұрын
@@mateuszwojciechowski495 thanks for the reply, isn't users state in the dependacy array, and on increment aren't we updating users state?
@joachimfrank4134
@joachimfrank4134 Жыл бұрын
Without useMemo the function runs in each rendering of the component, even if no state was changed.
@rohan1765
@rohan1765 Жыл бұрын
@@joachimfrank4134 Ohh I get it now, thanks 🙂
Жыл бұрын
your useMemo will get re generated every time you click "increment" because you are doing a .map and that's generates a new array so the depenecy array of useMemo will be a new one so your useMemo makes no sense 🙂
@timgerk3262
@timgerk3262 Жыл бұрын
This is a profound example of by-reference intuition from the real world blowing up on a learning coder. Does Javascript make this any harder, by being subtle about objects vs primitive value ?
@black_platypus
@black_platypus Жыл бұрын
Oh, it's an easy trap to fall into for sure. I see "reference types vs value types" and mutation tripping up people all the time. But I wouldn't say objects vs primitives is compounding the issue much. You need to keep track of what you're referencing in any case
@LeonardoHernandezIC
@LeonardoHernandezIC Жыл бұрын
UseMemo would work only if you are creating a new array each time you update a element ... I there is still a optimization there
@shivansharjit7385
@shivansharjit7385 Жыл бұрын
Anyone knows about how to create a javascript sdk ?
@blyatMail
@blyatMail Жыл бұрын
dudeee.. i'm confusseeeddd.. this is too faaasssttt...
@yoJuicy
@yoJuicy Жыл бұрын
is there a way that writing a test would catch this? i dont know tests
@reinoob
@reinoob Жыл бұрын
You can compare the state and the variables during a test, but it isn't a good thing to test, you should test the funcionalities themselves and how the app is behavioring. For instance in this case the test should be that "if i increment a selected user, both lables should show the same information".
@romanmed9035
@romanmed9035 Жыл бұрын
useMemo also have a cost. cost of useMemo need compare with cost render.
@sameerkumarkalyanshetti3335
@sameerkumarkalyanshetti3335 Жыл бұрын
I'm facing a problem in making website responsive....could u plz help me out?...I will ask my doubt if u replied to this message.....
@VanPetersonKpoti
@VanPetersonKpoti Жыл бұрын
Thanks a lot. it seems simple, but not.
@namanjindal3089
@namanjindal3089 Жыл бұрын
Please also share this code, else it gets very difficult to expirement with it
@keyurgadher6729
@keyurgadher6729 Жыл бұрын
Awesome
@GuRuGeorge03
@GuRuGeorge03 Жыл бұрын
in other words: if u want referential data, u need to store a reference and not the data
@kashug.
@kashug. Жыл бұрын
yeah, the example is more about having copies of data, in those cases you need to make sure you update all the copies. It is not really derived data since you can not derive selectedUser from the state before he added selectedUserId to the state.
@jeremy_s
@jeremy_s Жыл бұрын
What's the possible/potential bug here? I don't see any issue with storing the selected user object in state, please provide a concrete example of a potential bug from applying this pattern as opposed to "bad things can happen".
@cristianpache5303
@cristianpache5303 Жыл бұрын
He explained it, when he incremented the age of the user on the list, the age of the selected user wasn't changing, because it was stored as a separate state. It is really a bad practice to store the object in a state, because if you do that, you'll have a duplicate state (the user on the list and the same user on the selectedUser state), and you'd have to update both states manually when some attribute of the user changes (in this case, the age)
@jeremy_s
@jeremy_s Жыл бұрын
Yeah glazed over that at 3 in the morning, agreed, thanks!
@mohamadmohamad4242
@mohamadmohamad4242 Жыл бұрын
well, good solution but this solution as you said had bad performance since you need to loop in the users' array to find the selected user, 1)alternative solution is to store the users in an object instead of an array like this: const [users, setUsers] = useState({ 1: { name: "keyle", age: 27, }, 2: { name: "sally", age: 30, }, 3: { name: "mike", age: 25, }, }); and now the selected state can be any id (1,2,3) and you can access the selected user object with o(1) and you can make an array of users id to keep track of their sequence like this: const sequence = [2 , 1 , 3] 2)another solution is to keep the users state an array of obj like you did but instead of saving the user id in the selected state, we can just save it is index (since the order does not change) thank you for the video amazing
@LoryKa
@LoryKa Жыл бұрын
awesome way of thinking. i have to master this way of thinking because usually i have to deal with performance issues in my apps.
@sevenstars0711
@sevenstars0711 Жыл бұрын
Looping over the array every time the component re-renders is bad, but by using useMemo you get rid of this problem, and you only loop when you need to. There's no need to fundamentally change your code by using objects or some other ways
@mrhenry60412
@mrhenry60412 Жыл бұрын
what if we just add a state in users like this: const [users, setUsers] = useState([ { id: 1, name: "keyle", age: 27, isSelected: false, }, { id: 2, name: "sally", age: 30, isSelected: false, }, { id: 3, name: "mike", age: 25, isSelected: true, }, ]);
@GuthixCss
@GuthixCss Жыл бұрын
@@mrhenry60412 Then we´d still have to loop through the users to find the one that is selected. It would also add complexity since we´d have to unselect one user when the next one is selected.
@mrhenry60412
@mrhenry60412 Жыл бұрын
@@GuthixCss well, I just don't think that creating a hook to store id is necessary, when you can manage all user-related info together. What if you need to deal with some functionality like hiding selected user or changing the font color of selected user at the same time?
@lucienchu9649
@lucienchu9649 Жыл бұрын
For me, the tricky part is hunt down the performance issue.
@vitorwindberg4212
@vitorwindberg4212 Жыл бұрын
or you can just add a prop to the user you select like selected: true and then you have all your control in only one state :)
@andy-ally
@andy-ally Жыл бұрын
You will face another issue in this case. You will need to find currently selected user and set selected to false which in this example is not a big problem, but if you start keeping track of different object states and behaviors inside an object itself it could become a huge pain to update and maintain.
@narendrareddyyarramreddy2007
@narendrareddyyarramreddy2007 Жыл бұрын
useMemo() doesn't have any use in this component because it has both the state variables in the dependency list! So, whatever we do in this component, it'll run the loop through the whole users list to find the selected user
@brendon205
@brendon205 Жыл бұрын
because it's just an example, in a real application you'll gonna have a lot more states than that
@narendrareddyyarramreddy2007
@narendrareddyyarramreddy2007 Жыл бұрын
@@brendon205 yeah makes sense 👍
@mrcookie97
@mrcookie97 Жыл бұрын
iirc the beta.reactjs docs talk about this. Basically never store the same data multiple times in state. Only one copy. Best solution is selectedUser to be an id or index
@jean-francoisbouzereau6258
@jean-francoisbouzereau6258 Жыл бұрын
This is the "Single Source of Truth" principle
@xice111
@xice111 Жыл бұрын
you can select only id, and pick it by id
@rubenverster250
@rubenverster250 Жыл бұрын
Best drugs ever man :D Will be teaching this to some Juniors soon ^-^ It's nice having mid-senior code teaching. Very difficult to get
@doc8527
@doc8527 Жыл бұрын
Please hold on a second before u try to teach your juniors (I call myself junior level too sometimes :p), there are few problems with this example and solution. For the example itself, check the top comments with highest vote regarding the definition of derived state. I want to point out the problems with that solutions from some of the comments and the video, the video example is really tricky. First, some of comments say use array index so you don't need to use array.find(), it's questionable/wrong to use array index id as selectedUserId cuz the array index will cause bug once the array size changed hence index is not longer unique. If u pretty sure the size and position are static under any circumstances. This approach is probably the most performant and simplest solution Second, use the unique user id as the find id. This is the video solution, it's good but when the size is large, it will cause performance issue as the video claimed later. However, the useMemo() in this case, doesn't solve the performance issue because when you update the selection, it will modify the array hence cause useMemo() to rerun. the useMemo will be useful only when the parent container is changed but at the same time you don't want to re-render the current selection list. But for this example with its context, the useMemo() solution is simply wrong. the trouble array.find() will still run regarless. So what's my answer? I would say if the list is large, the performance is important, the initial code is fine. You just need to update both selectedUser & users when you call the update, and only update selectedUser if the user id is matching the updated user in users list. You don't even need to use the array.find() and useMemo() in the first place, it also reduces the mental overhead of using memo hooks. The root issue of his solution is because the "issue" example he provided doesn't match the definition of derived state. It just looks like it, that's why I called it tricky. If the example is derived state, you shouldn't need useMemo() most likely.
@mikesummer670
@mikesummer670 Жыл бұрын
What is the point of useMemo at this case, because if we increment any user age or select new one, there still be .find through list (because there is no other case for rerender), instead we could store key - value object where key is user id and value is user, so we would not need iteration
@anniecenter
@anniecenter Жыл бұрын
This is a very simplified example so that it’s easier for beginners to understand. He mentions in the video that this is useful if you have other state or props making the component rerender, like theme for example.
@arjobansingh1940
@arjobansingh1940 Жыл бұрын
This is jus an example, Real world app would have lot of other states which could cause render. And using object to store data, with userId as key do look okay on surface. But it also has same problem. Cause React cannot render object, you have to create array of users form users object using Object methods like Object.keys, entries etc on every render which would always he O(N) and than map over that array to show users. Basically we are back to same problem, either use state as array of objects and avoid creating array in every re-render ans use filter to find sleeted item. Or use object of users with keys being userIds and create array from this object to map over in every re-render
@mikesummer670
@mikesummer670 Жыл бұрын
@@anniecenter You if have list with 1000 users and change age to one of them - your array is changing, so it will be .find again through 1000 users even if you did not change selected users and useMemo won't help you with that.
@mikesummer670
@mikesummer670 Жыл бұрын
@@arjobansingh1940 You could also store array of IDs, so you will map through array of IDs and get users from key-value storage
@arjobansingh1940
@arjobansingh1940 Жыл бұрын
@@mikesummer670 again we are storing two states for one data source.. Exactly the problem this video tried to solve. In real world scenarios, we would have feature of adding, deleting users. You would have to manage state at both the places with this approach. But yeah, dependent on use case, if problem statement is not much complex, storing an array for ids differently could be used
@huzbum
@huzbum 11 ай бұрын
As an angular developer forced into react, it seems to me that react is prone to bugs. You have to get everything right, every time, or you get bugs and/or poor performance.
@otherstuff1833
@otherstuff1833 Жыл бұрын
updating a state using a callback function is also a solution I guess and no need to use extra hooks, so what do you think about that 🤔🤔
@jilhenry
@jilhenry Жыл бұрын
I like his eyes
@ceasardg
@ceasardg Жыл бұрын
November 4, 2019
@ash__borne
@ash__borne Жыл бұрын
And finally third
@adityanayak20
@adityanayak20 8 ай бұрын
Update Suggestion: This video is not embedded in your blog article.
@IdleAtre
@IdleAtre Жыл бұрын
when i watch videos like this one, i am glade i chose svelte over react.
@thiagohartman5259
@thiagohartman5259 Жыл бұрын
I think using useMemo is overengineering. React developers themselves talk about not doing performance optimizations where there is no bottleneck
@JustCode39
@JustCode39 Жыл бұрын
Vue, computed
@riceymix4688
@riceymix4688 Жыл бұрын
Vue: just use computed
@aarongillies2900
@aarongillies2900 Жыл бұрын
Vue makes this so much simpler
@acabreragnz
@acabreragnz Жыл бұрын
Why?
@awekeningbro1207
@awekeningbro1207 Жыл бұрын
2:22, here one way to solve this is: instead of returning a new object in the map, you can do: if(user.id === id) { user.age += 1; } return user; this will solve this reference inequality issue. However, you should keep this in mind that you are mutating the object.
@narendrareddyyarramreddy2007
@narendrareddyyarramreddy2007 Жыл бұрын
Mutating the object will lead to a new bug since the component will not re-render as we are returning the old object Reference.
@awekeningbro1207
@awekeningbro1207 Жыл бұрын
@@narendrareddyyarramreddy2007 your justification is partially incorrect because that's not how re-render is happening. The array reference is what is being tracked off from state and since .map() returns a new array, this new array and old array is referentially different so react will cause a re-render regardless
@narendrareddyyarramreddy2007
@narendrareddyyarramreddy2007 Жыл бұрын
@@awekeningbro1207 If I want to return a new object, I would prefer the conventional way of spreading everything and changing required ones.. It looks more cleaner 🤔
@arjobansingh1940
@arjobansingh1940 Жыл бұрын
@@awekeningbro1207 for this example you are right, array change is causing re-render. But consider a case, where each row is a new User component which takes user and renders it’s age and that User component is memoized with memo() HOC as well for performance reasons, as there can be tons of rows, and re-rendering every row just so because some parent’s different state is changed or data of some single row is changed, is not feasible. Now here, each User component only have user prop, based on its change the User component can re-render. But now with your approach, each user object is mutated on age change, thus User component will not re-render, causing old age to render on UI. Yeah, you could say that in current case, that is not the problem, but we should write code in a correct way, which can be easily extended. Thus we should follow React’s principal of not mutating state. Instead of writing React’s code in non-recommended way, and then trying to figure out in future why certain thing is not working on extended features or codebase!
@cmlttnts4906
@cmlttnts4906 Жыл бұрын
Please don't suggest bad practice, that might be working in this case but mutating state is very bad, you will encounter so many bugs doing that
@stepanzavadil
@stepanzavadil Жыл бұрын
Why not just store the reference?
The Easiest React Hook
6:41
Web Dev Simplified
Рет қаралды 60 М.
Why Signals Are Better Than React Hooks
16:30
Web Dev Simplified
Рет қаралды 443 М.
Не пей газировку у мамы в машине
00:28
Даша Боровик
Рет қаралды 2,1 МЛН
Trágico final :(
01:00
Juan De Dios Pantoja
Рет қаралды 18 МЛН
Kitten has a slime in her diaper?! 🙀 #cat #kitten #cute
00:28
I PEELED OFF THE CARDBOARD WATERMELON!#asmr
00:56
HAYATAKU はやたく
Рет қаралды 24 МЛН
Junior Vs Senior Code - How To Write Better Code As A Web Developer - React
21:48
6 State Mistakes Every Junior React Developer Makes
15:53
Lama Dev
Рет қаралды 261 М.
How To Actually Get Hired In 2024
10:43
Web Dev Simplified
Рет қаралды 185 М.
NEW GPT-4o: My Mind is Blown.
6:28
Joshua Chang
Рет қаралды 70 М.
State Managers Are Making Your Code Worse In React
13:33
Web Dev Simplified
Рет қаралды 138 М.
Goodbye, useEffect - David Khourshid
29:59
BeJS
Рет қаралды 492 М.
3 React Mistakes, 1 App Killer
14:00
Jack Herrington
Рет қаралды 112 М.
10 Tailwind Classes I Wish I Knew Earlier
13:31
Web Dev Simplified
Рет қаралды 151 М.
Не пей газировку у мамы в машине
00:28
Даша Боровик
Рет қаралды 2,1 МЛН