The reason the second fix works: In both cases, App is responsible for rendering DirectChild, so in both cases, DirectChild will re-render when App re-renders. After the refactoring, App is no longer being re-rendered when the state changes; only MyProvider is. Because App no longer needs to be re-rendered, DirectChild does not need to be re-rendered.
Great job sir, there is few content creators like you who dive deep into JS stuff... I'm always enjoyed watching your videos hopefully you never stop that . BestRegards
Great explanation! I've been using this pattern (Context + reducer) and so far I'm very satisfied with it. I just want to leave a question about a use case that might occur: Imagine that instead of one DeeperChild, you have a list of them. Any change of the context's state triggered by one of those components will trigger a re-render in the remaining ones. Do you see any way of avoiding this or you wouldn't care about it? Best regards
Hey Tiago! Thank you :) I think the easiest approach would to potentially put a component in between the provider and its array of children, and then you could memoize that component wrapper rather than each of the children individually. But, for the most part I don't worry too much about performance unless it actually becomes a problem. It's easy to micro optimize things that don't actually matter :D
Hi. In your first example, if DirectChild and DeeperChild had other components in-between - they would not re-render on toggleTheme only DirectChild and DeeperChild will be re-rendering? right?
Good stuff mate. Just a question. Let's say you have a list that you need to order and filter. Would you use context for setting the filters, ordering the list, etc? Thanks mate
I don't think there is a definitive rule of when to switch from passing state as props to a child vs using context. I think maybe 2 levels fine, but 3+ maybe switch to context?
What a great video i hope you make more videos about context and how to imporve its performance especially in large apps Is there any way to avoid the rerendering that happens when you use useContext inside a component My work flow is like this I have a global context and global states that have to be shared across many components some of these states arent related to each other and some are So when i use them inside many component some components rerender themselves when they shouldnt rerender themselves they just rerender themselves because I'm using useContext inside them and using some global states that are inside that context I hope you understood my issue so far there is no performance issues at all but i was just wondering why is this happening whey these components get rerender every time another state in another component got rerender and the only reason i saw is because i'm using useContext inside them and inside it im pulling out some state from that global context
There will be a problem if you have another state like toggle and setToggle in Context and you import it in Direct child component and then if you change the value of theme in deeper child ,it will re render both direct and deeper child ,even we did not changed the value of toggle in direct child , can you solve that issue ???
Nice video, thanks. A couple of comments: 1. The trick with not needing to memioze if using the "children" prop was new to me. This needs some further digging, I feel like something might be missing here. Is this documented somewhere? 2. Perhaps you should also memoize the context value? In this case the context value is always going to be a new object, but since you are creating the context value in App (which is never re-rendered) then it's not a problem after all. If this theme provider was also rendered further down the tree, it would probably re-create the context value too often and hence invalidate the children too often as well.
Thanks, Einar! Both are great points! Yea... the children thing, I am not sure either why it doesn't re-render when done like that. And for sure, memoizing value makes sense... I suppose for the most part I try to put my providers as high up the tree as possible, because generally they are for the entire app, but that may not always be the case. I sort of wish objects were deep compared so that they didn't have to be memoized, but that would probably bring other unsuspecting issues :)
Hoooooo, good question! If I were to take a guess, it's because when you embed {children} and the JSX is converted into JS, React treats it as a collection (because there could be multiple children), or at least differently than if you just have the component directly nested underneath. Maybe it wraps a fragment around the children? I'm honestly guessing a little bit... I'd probably feel more comfortable going with the React.memo approach because it makes a little more sense as to why it doesn't re-render.
@@leighhalliday well, I wrote exported provider for my form lib, so it is already includes the children approach. So this is a case where the provider you will use in several places.
@@leighhalliday Honestly as someone who primarily uses React, I do really like the dependency injection/service paradigm that angular uses. I suppose MobX is pretty close to that
Hey! If you have a component (rather than {children}) directly as a child of your context provider, you may want to wrap that top level child in a React.memo to avoid unnecessary re-renders.
The reason the second fix works: In both cases, App is responsible for rendering DirectChild, so in both cases, DirectChild will re-render when App re-renders. After the refactoring, App is no longer being re-rendered when the state changes; only MyProvider is. Because App no longer needs to be re-rendered, DirectChild does not need to be re-rendered.
Thanks Kevin! Appreciate the insight.
But why is that? Doesn't react rerender everything in a subcomponent tree unless memoized?
Isn't it bc MyProvider is wrapped in a closure?
Great job sir, there is few content creators like you who dive deep into JS stuff... I'm always enjoyed watching your videos hopefully you never stop that . BestRegards
Thank you very much, Charli! Plan is for at least 1 video per week this year :)
I like that you always make your videos short and informative.
Thanks, Shak! I do my best :)
Thank you for the explanation!
I was actually using the second method without understanding why 😅
Hey Lotfi! I'm happy that the video was useful! Thanks for saying hi :)
I am very happy to have stumbled upon your channel! Excellent content and explanations !! Thanks man!
Hey straight edge hacker! Thank you very much :) New content hopefully coming weekly!
Succinct video that is direct to the point. I enjoy your videos. Thanks for creating them!
You're very welcome, Mark! Glad you enjoyed it :)
This video earned you a subscription. Great explanation!
Hey Ivan! Welcome :D
Same goes with me! 😂
Great explanation! I've been using this pattern (Context + reducer) and so far I'm very satisfied with it.
I just want to leave a question about a use case that might occur:
Imagine that instead of one DeeperChild, you have a list of them. Any change of the context's state triggered by one of those components will trigger a re-render in the remaining ones. Do you see any way of avoiding this or you wouldn't care about it?
Best regards
Hey Tiago! Thank you :) I think the easiest approach would to potentially put a component in between the provider and its array of children, and then you could memoize that component wrapper rather than each of the children individually. But, for the most part I don't worry too much about performance unless it actually becomes a problem. It's easy to micro optimize things that don't actually matter :D
Hi. In your first example, if DirectChild and DeeperChild had other components in-between - they would not re-render on toggleTheme only DirectChild and DeeperChild will be re-rendering? right?
Good stuff mate. Just a question. Let's say you have a list that you need to order and filter. Would you use context for setting the filters, ordering the list, etc? Thanks mate
I don't think there is a definitive rule of when to switch from passing state as props to a child vs using context. I think maybe 2 levels fine, but 3+ maybe switch to context?
What a great video i hope you make more videos about context and how to imporve its performance especially in large apps
Is there any way to avoid the rerendering that happens when you use useContext inside a component
My work flow is like this
I have a global context and global states that have to be shared across many components some of these states arent related to each other and some are
So when i use them inside many component some components rerender themselves when they shouldnt rerender themselves they just rerender themselves because I'm using useContext inside them and using some global states that are inside that context
I hope you understood my issue so far there is no performance issues at all but i was just wondering why is this happening whey these components get rerender every time another state in another component got rerender and the only reason i saw is because i'm using useContext inside them and inside it im pulling out some state from that global context
1:35 lol, when you said “it will be dark” my youtube app went all black then crash
Haha perfect timing!
Wow, another awesome video. Thank you very much
Thanks Alan, I appreciate it!
There will be a problem if you have another state like toggle and setToggle in Context and you import it in Direct child component and then if you change the value of theme in deeper child ,it will re render both direct and deeper child ,even we did not changed the value of toggle in direct child , can you solve that issue ???
Nice video, thanks. A couple of comments:
1. The trick with not needing to memioze if using the "children" prop was new to me. This needs some further digging, I feel like something might be missing here. Is this documented somewhere?
2. Perhaps you should also memoize the context value? In this case the context value is always going to be a new object, but since you are creating the context value in App (which is never re-rendered) then it's not a problem after all. If this theme provider was also rendered further down the tree, it would probably re-create the context value too often and hence invalidate the children too often as well.
Thanks, Einar! Both are great points! Yea... the children thing, I am not sure either why it doesn't re-render when done like that. And for sure, memoizing value makes sense... I suppose for the most part I try to put my providers as high up the tree as possible, because generally they are for the entire app, but that may not always be the case. I sort of wish objects were deep compared so that they didn't have to be memoized, but that would probably bring other unsuspecting issues :)
Very good video, thanks.
Would you explain please, why with {children} it doesn't do the unnecessary rerender
Hoooooo, good question! If I were to take a guess, it's because when you embed {children} and the JSX is converted into JS, React treats it as a collection (because there could be multiple children), or at least differently than if you just have the component directly nested underneath. Maybe it wraps a fragment around the children? I'm honestly guessing a little bit... I'd probably feel more comfortable going with the React.memo approach because it makes a little more sense as to why it doesn't re-render.
@@leighhalliday well, I wrote exported provider for my form lib, so it is already includes the children approach. So this is a case where the provider you will use in several places.
Perfect :)
react-final-form build on this "Providers -> children" approach
Really great video. Thank you.
Thank you Hadi!
Finally got the answer.. Thank you alot
Excellent!! Glad you got it figured out :)
What if you had dependent contexts like TableContext => RowContext => RowDetailsContext? Would you have to memoize at each level?
That's a great question... I'm just guessing :D but I think I would say just put 1 after all the providers.
@@leighhalliday Honestly as someone who primarily uses React, I do really like the dependency injection/service paradigm that angular uses. I suppose MobX is pretty close to that
Now you have video quality greater than 360p, thanks for that.
lol... I always do, it just takes UA-cam a tiny bit to process the HD version after launching a new video :D
@@leighhalliday i didn't know this youtube process. Thanks for the info.
@@MoT-MasterOfThings lol
Thank you!
You're welcome! Glad you enjoyed it :)
excellent explanation.
Thanks Sw yx!
We can provide context to components as a child prop of the provider and not as a direct child.
i have to wrap one level top component with react.memo before component that will useContext?? sorry if my english is bad heheh
Oh wait. I think, use react.memo on component that i dont want to rerender. Right?
Hey! If you have a component (rather than {children}) directly as a child of your context provider, you may want to wrap that top level child in a React.memo to avoid unnecessary re-renders.
Your videos are the best
Thanks so much :D I appreciate the support!
Great video!
Thank you Zach!
Glad I did the child thing from day 0
Nice vídeo!
Thank you Rafael!
good shit!
Thank you :)
Cool
😎
use a clean context from react-hooks-in-callback npm package:
www.npmjs.com/package/react-hooks-in-callback
npm i -S react-hooks-in-callback
import { createContext } from "react-hooks-in-callback"
const { Provider, useContextSelector } = createContext(defaultValue)
thanks
What does it do Motema?
Hello
Hey there Phan!