This Context API Mistake Ruins Your Whole React App (All Components Re-Render)

แชร์
ฝัง
  • เผยแพร่เมื่อ 1 ธ.ค. 2024

ความคิดเห็น • 101

  • @ByteGrad
    @ByteGrad  9 หลายเดือนก่อน +2

    My Professional React & Next.js course is OUT NOW now! Find it here: bytegrad.com/courses/professional-react-nextjs -- this is the #1 resource to master the latest React & Next.js, my absolute best work.

  • @ShantanuAryan67
    @ShantanuAryan67 ปีที่แล้ว +130

    3:15 the actual problem is - you defined state on App. whenever state changes the entire app rerenders, which includes the two example components. context is not the issue here.

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +13

      Yep, but beginners make this mistake in conjunction with the Context API

    • @ShantanuAryan67
      @ShantanuAryan67 ปีที่แล้ว +31

      the actual solution is
      - define state where it is needed
      - use composition to insert rendered trees directly in component

    • @ShantanuAryan67
      @ShantanuAryan67 ปีที่แล้ว +1

      fair enough 👍

    • @ukaszkrzywizna1756
      @ukaszkrzywizna1756 ปีที่แล้ว +15

      Thank you for this comment! As a React-dev beginner, I was very surprised as to why the context would cause the rerender of a whole app. Now everything's clear :) To author: Putting aside other videos (which are very helpful), this one causes more confusion than help.

    • @anonymoussloth6687
      @anonymoussloth6687 ปีที่แล้ว +3

      Can you explain how his solution avoids this? Why doesn't this happen again in the solution since the other components are child components as well

  • @jotaroisdarius1918
    @jotaroisdarius1918 ปีที่แล้ว +57

    i have a small suggestion, you should make more video likes this and group them into a playlist titled "common react mistakes" or something similar. Keep going dude!

  • @piush787
    @piush787 10 หลายเดือนก่อน +8

    For those who still thinks why {children} did not render, the answer is in react docs:
    "When a component visually wraps other components, let it accept JSX as children. This way, when the wrapper component updates its own state, React knows that its children don’t need to re-render".
    @ByteGrad you are a savior but you must have mentioned this point too.

  • @rm_4848
    @rm_4848 ปีที่แล้ว +26

    @2:45 Both components are re-rendering because of the state update in the parent, not specifically because of context usage.
    @3:47 You moved the state from the parent to the component level, so that’s why the other component doesn’t re-render.

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +2

      Yes, all true

    • @jackn
      @jackn ปีที่แล้ว +4

      @@ByteGrad I still don't follow. In both cases, `CountContextProvider` and `App` are parent components with a `useState`. The only difference is in `CountContextProvider`, the `children` are passed as props and not as static JSX components. Why would a state change in `CountContextProvider` not cause the `children` props to re-render?
      I feel like there's some important information missing here

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +13

      Yeah, it’s tricky. What it comes down to is that the {children} pattern has special behavior that prevents that re-rendering. I might do a separate video on this

    • @The14Some1
      @The14Some1 ปีที่แล้ว +2

      @@ByteGrad Yes, please, make a followup, explaining this special behaviour. Recently i've watched Jack Herrington's video about context called "Making react context Fast" and he solves this problem in completely different way. I guess he is also not aware about this special behaviour of children.

    • @nark4837
      @nark4837 ปีที่แล้ว +1

      I would also love this!@@ByteGrad

  • @imfad3d
    @imfad3d 9 หลายเดือนก่อน +1

    I've been using the right way for quite a while now but never bothered to know why. This video really puts thing in perspective. Good one.

  • @stashladki2594
    @stashladki2594 ปีที่แล้ว +7

    Yeah, context API is definitely a tricky one, especially now with RSC's coming into play, I find that if properly done you almost never actually need to use contexts, less is more ;)

    • @wlockuz4467
      @wlockuz4467 ปีที่แล้ว

      using vanilla React with vanilla hooks is like shooting yourself, you just get to choose which weapon is it each time.

  • @vineetsingh904
    @vineetsingh904 8 หลายเดือนก่อน +3

    i watched your 2-3 videos and all the mistake which you told I was making in my app but now i am fixing them. Your channel content is just like having a personal mentor.

  • @andrewmcmaster7123
    @andrewmcmaster7123 ปีที่แล้ว +7

    That was a really nice demo! I had my code split like that but I didn't know that there was such a good reason for it to be done that way. Thanks for your well thought out and easy to understand video 🙂

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว

      No problem 👍

  • @bob_factory
    @bob_factory ปีที่แล้ว +6

    I don't quite understand. I know the rerendering was caused by the state object on the main App function but even if you move the state over to another component shouldn't the children also rerender since the provider components state is being updated ?

    • @ukaszkrzywizna1756
      @ukaszkrzywizna1756 ปีที่แล้ว +7

      I think that this text from official docs applies here:
      "When a component visually wraps other components, let it accept JSX as children. This way, when the wrapper component updates its own state, React knows that its children don’t need to re-render."

  • @MyGeorge1964
    @MyGeorge1964 ปีที่แล้ว +2

    Keep 'em coming they're like little gems - thank you!

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว

      Thanks, more to come

  • @Euquila
    @Euquila 10 หลายเดือนก่อน

    I really love this video because it highlights some deep nuances in react. However, I feel like everyone is lost here, so **here goes**: The difference in rendering behavior stems from how components are incorporated into the component tree (direct inclusion vs. passed as children) and their data dependencies (like props, state, and context).

  • @nark4837
    @nark4837 ปีที่แล้ว +6

    This is great! I'd love for an explanation as to why simply moving the provider logic to a separate component stops both children from rerendering?

    • @nhathuynguyen716
      @nhathuynguyen716 ปีที่แล้ว

      yeah good point

    • @thecyberhobbit
      @thecyberhobbit ปีที่แล้ว +3

      This is exactly what I was wondering when he started moving it and said to myself "why would that make any difference?"... to me it's those components are still be rendered INSIDE that raw context code.

  • @Cypekeh
    @Cypekeh ปีที่แล้ว +1

    Your videos are excellent. I got my first job as a react junior and I love how you explain thoroughly explaining your thought process

  • @thebocksters2756
    @thebocksters2756 3 หลายเดือนก่อน +2

    The fact the component didn't rerender is because, this child compoents are passed as children prop. The children prop never change. Its the same prop in the parent for all of iis rerenders. So these two child components are the same between rerenders, of course, that uses the useContext will re-render. I know that from 'Developer Way' utube channel

  • @Bread-vk8fl
    @Bread-vk8fl 6 หลายเดือนก่อน +1

    AMAZING! Simple and straight to the point

  • @giorgos6576
    @giorgos6576 ปีที่แล้ว +3

    Very clever trick. Any idea why the React DevTools (Tested on both Chrome and FF) thinks that the ExampleComponent2 re-renders even though nothing is console logged?

    • @logicweaver7152
      @logicweaver7152 5 หลายเดือนก่อน

      How do you check what's rerendering using react dev tools?

    • @deanolium
      @deanolium 2 หลายเดือนก่อน

      @@logicweaver7152 Go to the component tab, then click on the gear icon and there's an option to highlight on component rendering. It'll then put an outline over each component that's rendering, which makes it really easy to see what's going on in your app.

  • @callegarip
    @callegarip 7 หลายเดือนก่อน +1

    Thank you!. But what about if the ExampleComponent2component still needs to use the context but for a different state? Will clicking on the count button in ExampleComponent1 re-render ExampleComponent2 component?

  • @sck3570
    @sck3570 ปีที่แล้ว +2

    Wow I didnt know that, now I have a monumental task ahead of me

  • @marshalldteach1109
    @marshalldteach1109 20 วันที่ผ่านมา +1

    thank you, this solves my problem with my react application

  • @user-pw5do6tu7i
    @user-pw5do6tu7i ปีที่แล้ว +2

    This video was clutch. Any suggestions for multiple contexts?

    • @Aashutosh_kumar
      @Aashutosh_kumar ปีที่แล้ว +1

      You can use the same pattern of creating multiple contexts as separate component and wrapping them around the components that consume that context.

    • @Aashutosh_kumar
      @Aashutosh_kumar ปีที่แล้ว +1

      One catch though, If you are working with normal React its fine, but If you are working with NextJs you should mark the component as client component by "use client" at the top of the file.

  • @miraclenerdkidchiki6249
    @miraclenerdkidchiki6249 ปีที่แล้ว +1

    Thanks so much for the tips and tricks...you are doing an excellent job
    Great delivery and explanation as well as well though out code examples

  • @guanbo-yang
    @guanbo-yang ปีที่แล้ว +1

    It's like you can't directly nested a server component inside a client component, but you can pass the server component as a prop such as children, right?

  • @YuretsUA
    @YuretsUA ปีที่แล้ว +1

    Cool, thanks, I saw such code a lot in the applications but I thought it was made just for separation of logic, but now I see that it has other sence.

  • @RADIOSCATRACHASUTAN
    @RADIOSCATRACHASUTAN 7 หลายเดือนก่อน +1

    Man, I switched to Zustand when I saw this behaivior happening.. nice!

  • @Vishtar_Official
    @Vishtar_Official ปีที่แล้ว +1

    Oh, i didn't thought about that. Thanks, man!

  • @richardpickman5574
    @richardpickman5574 ปีที่แล้ว +1

    So, ahhh, i trying to understand why this happends. I guess whole app component rerenders because app states changes, and then we using provider as wrapper component to let react just pass new arguments in reconciliation stage and avoid rerender, is it right or i am missing something?

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว

      Yeah it’s tricky haha. In the mistake example, the whole app re-renders because the app state changes. In the solution only the state in the provider component changes and the children are not affected by that because of the {children} pattern

  • @hedgedog7706
    @hedgedog7706 11 หลายเดือนก่อน +3

    Hello thank you very much for this video!
    I have a question - Why does every component render twice?

    • @daanw6270
      @daanw6270 10 หลายเดือนก่อน

      Only in dev mode

    • @hedgedog7706
      @hedgedog7706 10 หลายเดือนก่อน

      @@daanw6270 yeah but why

    • @b25671
      @b25671 4 หลายเดือนก่อน

      @@hedgedog7706 It's by design by react for catching bugs. If your functions are not pure, their results will show unwanted results when rendered twice. It's explained in the docs.

    • @hedgedog7706
      @hedgedog7706 4 หลายเดือนก่อน

      @@b25671 yoo thank you but a little late i already got a job programming on this tech stack (next react prisma) it was very easy to learn

  • @oscardasilva971
    @oscardasilva971 ปีที่แล้ว +1

    I learn so much from you. Thank you so much

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +1

      Great to hear! 😊

  • @funnyanimalvideosshow7780
    @funnyanimalvideosshow7780 ปีที่แล้ว +1

    Can you also make more landing page videos like you did earlier. the portfolio website was awesome. Next time can you touch on various niches, like product based etc. thanku for teaching all of these good things. keep going you have my support

  • @wlockuz4467
    @wlockuz4467 ปีที่แล้ว +5

    This video is misleading. App re-renders because its own state changes not because of the context.
    What you did in CountContextProvider is no different than what you did in App, that is, you passed some children to a component.
    The real difference is that now your state is not bound to App, its bound to CountContextProvider. So as far as the App is concerned it has no state so it will never re-render, only the ExampleComponent1 which uses the context will re-render.
    As an experiment, if you you wrap your App in CountContextProvider and use useContext there, it will start re-rendering the whole thing again.
    0:20 in the example you say the ExampleComponent2 needs access to state but you don't actually end up passing it, so what is the point of lifting it up? This makes it a very contrived example that doesn't really help the point you're trying to convey.

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว

      Yep, all true, but this mistake is often made in conjunction with the Context API. It’s a contrived example, yes

    • @wlockuz4467
      @wlockuz4467 ปีที่แล้ว +1

      @@ByteGrad I think themes or login state are great examples for this

    • @The14Some1
      @The14Some1 ปีที่แล้ว +1

      @@wlockuz4467 Actually in case of themes rerendering of the entire app might be desired behaviour.

    • @dealloc
      @dealloc ปีที่แล้ว

      @@The14Some1 Or y'know you could just apply a class on the document root HTML and have CSS handle the rest through CSS variables and media query. No re-renders needed, other than updating the state for whatever toggle you may have. Or otherwise, use a and FormData.

  • @brunocrosier
    @brunocrosier ปีที่แล้ว +2

    nice! is there an eslint rule for this? 🤔

  • @rubadub_tv
    @rubadub_tv 10 หลายเดือนก่อน

    Why does it require a custom hook to understand the state being used in children? Isn’t the context provider component already taking in children?

    • @chidyommy284
      @chidyommy284 3 หลายเดือนก่อน

      I think the useContext hook is meant to be used in another file apart from the one it's created,so that you get the same context

  • @CistiC0987
    @CistiC0987 ปีที่แล้ว +1

    Amazing stuff, also can you please explain why it is working? It looks the same to me, you just extracted provider to a component, no? Is there some magic because of thr children pattern?

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +4

      Yeah I should have mentioned it’s because of the state in the app component that everything re-renders. Then the solution is to use the {children} pattern which won’t affect children when state changes

    • @Eliac77
      @Eliac77 ปีที่แล้ว

      @@ByteGrad, I was looking for the explanation. Thanks for clarifying it here. Awesome job.

  • @b25671
    @b25671 4 หลายเดือนก่อน

    How is the second component not rerendering? It's a child of the provider, provider does a state update, so rerenders, and therefore all descendants rerender... by definition. So why does this work?

    • @b25671
      @b25671 4 หลายเดือนก่อน

      Oh...ok it s probably because the childeren are actually not descendants... they're passed by an argument... so not contained by the provider. Therefore not rerendered. Interesting.

  • @aslamanver
    @aslamanver 9 หลายเดือนก่อน

    use memo, or get the state out of

  • @rajeshkumarrout1192
    @rajeshkumarrout1192 10 หลายเดือนก่อน

    wow thanks for such a deep explanation

  • @nikmish1
    @nikmish1 4 หลายเดือนก่อน +1

    very clean solution.

  • @prasadbroo
    @prasadbroo ปีที่แล้ว +1

    You told us which pattern to use but haven't told us reason behind it
    Sorry for my bad English😊

  • @yeasararefin007
    @yeasararefin007 ปีที่แล้ว +2

    Could you please make videos on :
    1. How we can perfectly index a Next.js 13 Website on Google, How to get Our site on google search.
    2. How we can integrate Google Ads in our Next/React website to earn from the site.
    I guess this topics are very important but we don't have enough content about this. Thanks.

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +1

      Thanks, good ideas

  • @SterlingCobb-x3c
    @SterlingCobb-x3c 6 หลายเดือนก่อน

    would be nice if you go into "why" this happens

    • @b25671
      @b25671 4 หลายเดือนก่อน

      See my answer. The childs are actually not childs... they're siblings. The context provider exposes it's state as a sibling, not as a parent.
      At leaat that's the way I see it.

  • @rosan5657
    @rosan5657 ปีที่แล้ว +1

    can you make react-redux course please.

    • @ByteGrad
      @ByteGrad  ปีที่แล้ว +1

      My React & Next.js course will have Redux too. Make sure you’re subscribed to the email list :)

    • @rosan5657
      @rosan5657 ปีที่แล้ว +1

      @@ByteGrad your videos are So informative then regular courses Thank You.
      btw m from Nepal

  • @ziat1988
    @ziat1988 ปีที่แล้ว +1

    so should we get rid off context api and choose other state library like redux , zustand ...?

  • @ritikraj.18
    @ritikraj.18 8 วันที่ผ่านมา

    your voice is just too seductive. love from bermuda triangle

  • @almuzahmi12345
    @almuzahmi12345 6 หลายเดือนก่อน

    Live long bro,

  • @DjLeonSKennedy
    @DjLeonSKennedy ปีที่แล้ว

    It's cool but for me who nows why it's working like this, video should describe it also I think

  • @icodejs
    @icodejs ปีที่แล้ว

    I tried this out and it works as you suggested in regards to console.logs, but when I select "Highlight updates when components render" within React DevTools, it still tells me that there was a re-render in both components. Any ideas? Maybe I'm doing something wrong 😊

    • @dealloc
      @dealloc ปีที่แล้ว +1

      That is a bug in React DevTools because that feature hooks into the function calls. React calls all functions (including components) on every render. However, every render does not equal a function call. Nor does a render necessarily result in a DOM update. If you try to wrap your inner component's JSX in a single Fragment it should no longer highlight.
      Really you should consider using the profiler more than React DevTools for performance instrumentation that _actually_ has an affect. React DevTools is only really useful for searching through the VDOM tree for the most part.

  • @anuragnair5672
    @anuragnair5672 ปีที่แล้ว +1

    nice!

  • @terjeber
    @terjeber 6 หลายเดือนก่อน +1

    You should always use Typescript when developing React apps, none of this code compiles if you use TypeScript, which means there is something wrong with the code.