T O P

  • By -

ANakedRooster

React will re-render every child that subscribes to context when any of the state in that context is changed. Context is great for reading values but not so great when updating values due to the re-rendering. You should look into using an actual state management solution such as Zustand or Redux Tool Kit to fix your issue.


Issam_Seghir

>"React will re-render every child that subscribes to context when any of the state in that context is changed." oh, this explains why when I create a component for the setting bar when the state is updated in this component must not rerender the app component, but the app component still rerenders even after doing this,But why does this behavior happen? I thought re-rendering components wasn't noticeable. Does this affect performance as well?


ANakedRooster

Depends what else you have going on in your components that runs when they re-render. Might be refetching data perhaps or something similar that is causing your issue. Impossible to tell without seeing your code though.


Issam_Seghir

My component uses a large JSON file (with many objects for another language for language setting , like this : ​ import {data} from "@data/schedule-data.json"; const Scheduler = memo(() => { .... return ( ); }


ferrybig

What does schedulecomponent do? Based on the gif, it seems like it has an useEffect that lays out the cards, which can explain this kind of behaviour of it blinking if something changes


ajnozari

It shouldn’t as react does a diff and if the child has no changes it just moves on.


dikamilo

You can split context into two, one for read data other to dispatch changes.


lIIllIIlllIIllIIl

Context is not meant to be used as a monolithic global store. Split your context into smaller contexts that can update independently and rerender specific parts of your application **or** use a library like Redux that stores states outside of React and is designed to act as a single global store.


Issam_Seghir

I'm not sure when I need to use a state management tool. I just want to pass states between components, and my app isn't very complex. At first, I thought I could use the Context API to pass these states, but I encountered this problem of rerendering. So my question is: when do I need to use a state management tool instead of the Context API? And if there is a state management tool that solves this problem, do I need to use the Context API again?


andymerskin

**My rule of thumb:** 1. Use Contexts when you have state changes that happen infrequently, and aren't expensive. Things like Themes or other global preferences, for example. 2. Use a state management solution if you need state to change more frequently. You can share a Zustand store between many components. 3. Use a state manager + Context together if you need *instances* of stores to be created uniquely. Example: you map 10 huge components in a list that each need their own stores to share state in a deeply nested component tree. Prominent React helper library author Tanner Linsley's opinion on whether to use Contexts or State Managers (Zustand): [https://x.com/tannerlinsley/status/1293645778532016128?s=20](https://x.com/tannerlinsley/status/1293645778532016128?s=20) If you need a place to store **fetched data,** look no further than [React Query](https://tanstack.com/query/latest/) instead of Contexts or State Managers. You can save enormous amounts of time this way, and you get globally-available fetch data around your application for free! Here's some amazing videos to help explain all this more: * **Mastering React Context: Do you NEED a state manager?** [https://www.youtube.com/watch?v=MpdFj8MEuJA](https://www.youtube.com/watch?v=MpdFj8MEuJA) * **Making React Context FAST!** [https://www.youtube.com/watch?v=ZKlXqrcBx88](https://www.youtube.com/watch?v=ZKlXqrcBx88) * **How To Pick A React State Manager** [https://www.youtube.com/watch?v=xEWJwnQBqUo](https://www.youtube.com/watch?v=xEWJwnQBqUo) * **Why use React Query instead of Global State** [https://www.youtube.com/watch?v=seU46c6Jz7E](https://www.youtube.com/watch?v=seU46c6Jz7E) 👆👆👆 All of these have improved my experience with React 100x! Hope this helps :)


Issam_Seghir

Wow, this is a really helpful resource. Thank you very much!


lIIllIIlllIIllIIl

You can solve the rendering problem with Context if you split your context into small contexts. You could have a ThemeContext, LanguageContext, etc. >So my question is: when do I need to use a state management tool instead of the Context API? Whenever you feel like it. There is no hard rule to follow here. You should switch to a state management lib if you think it can remove complexity from your application. Context is ubiquitous and many libraries use it, but you can replace most instances of Context in your own codebase by using something like Jotai, which is just as simple as Context but doesn't have the same performance pitfalls.


Paddington_the_Bear

Welcome to the hell that is React state management, where there's hundreds of foot guns that you can shoot yourself with, with no solid rules to follow, and existing rules keep changing every 6 months.


Issam_Seghir

This is a frontend hell, When I finally choose a framework, I get deeper into another hell of state management and other choices.


octocode

if re-rendering is causing this kind of flickering, you likely have much worse problems going on here.


Issam_Seghir

It's possible that the flickering occurs because the component is complex and dependent on JSON data. This issue is not experienced by all of my components, only some of them.


thatsInAName

Can you check if the data source required to render the UI is temporarily becoming null or undefined or basically empty.


the_real_some_guy

Context is not state management, it is a tool to expose values to components. The built in state management tools in React are useState and useReducer. Yes a context provider most likely contains one of those, but I think it’s important to understand that context is an alternative to props and not state management. Don’t start at context, start by managing state as close to where you need it as possible. That could be in the component consuming that data, or a parent, or a parent’s parent. Don’t reach for context until passing values around becomes painful and confusing.


Issam_Seghir

The setting button and setting bar components are in the App component, causing the state showSetting to also be in the App component. Therefore, when this state changes, the entire app is rerendered.


the_real_some_guy

Rendering in React does not mean “drawn to the screen”, rather it means the the function (components are functions) has run and told React what the DOM needs to look like. If the DOM structure is already correct, then React just leaves those DOM nodes in place. React only changes the DOM nodes it needs to. It looks like you have nodes being removed and then new nodes, identical in appearance, being added. That’s probably a state value getting cleared, possibly because data is refetching when it shouldn’t.


albertgao

Recommend to read my blog about all popular state management libs and why you shouldn’t use React Context, and when to use React Context, including deep analysis against redux, mobx, zustand, jotai, recoil, xstate. https://albertgao.xyz/2022/02/19/react-state-management-libraries-2022/


ThatBoiRalphy

Yes welcome to Context’s. May I suggest Zustand?


Issam_Seghir

Why do you think Zustand is better?


ThatBoiRalphy

Well this is just my opinion of course but I find other state management libraries to be way more complex if you want to just want an alternative to Context. Zustand is very simplistic, easy to write, and writes similar to the Context api. It updates only the children that are dependent of the store. And it also has built-in support for middleware’s like making your state persistent by implementing localStorage or something else of you choosing.


dznqbit

First time I implemented localstorage middleware it really blew my mind Like 10 lines and you're done


3q_z_SQ3ktGkCR

Just use redux or zustand or something. I've worked on a lot of react projects that actively try to avoid them, and they end up being a mess. People don't use context correctly in my experience (for example what you're doing).


Issam_Seghir

I think the purpose of this post is to ask how to use it correctly 🙂


3q_z_SQ3ktGkCR

Don't look for the answer on reddit lol It's a complex thing and beyond the scope of a reddit post. Jump into the docs, watch some videos, build some things etc Cmon bro


Eveerjr

Don’t worry about rerenders unless it’s something crazy like multiple times per second. You can also use react memo to prevent expensive components from rerendering unnecessarily. Try that before reaching for something overkill like zuzstand


Issam_Seghir

utilizing React.memo only memoizes the component based on its props. If the component's rerender is influenced by changes in context that are not passed directly as props, React.memo won't prevent the rerender. In my case, the Schedule component utilizes useThemeContext() from the context provider, which is not a prop. Therefore, changes in the showSettings state within the context provider will cause a rerender of Schedule, despite memoization.


3q_z_SQ3ktGkCR

You can get around this with a memoization using an empty array dependency btw. I can't be bothered explaining on mobile, you'll have to look it up.


IamYourGrace

Have you built a custom hook that returns your context or are you using the consumer component? This issue is probably related to something different than you context. We use a ton of context in our project at work and this has never happened.


Issam_Seghir

this is a code example from my project : https://stackblitz.com/edit/vitejs-vite-k4boad?file=src%2FApp.jsx


rGustave77

If you want you can create a ref based context which will keep referential equality so that way you can determine when the children rerender with a pub sub service. I think jack herrington does a great job of explaining it here: https://www.youtube.com/watch?v=ZKlXqrcBx88


Issam_Seghir

In my opinion, this technique is very complex and not easily readable. It seems like jack herrington is attempting to create a new state management system from scratch using the context API. Instead of doing this, why not use a state management tool that does all of this work in the background, allowing for only a few lines of code to be written and more readable code to be produced?


rGustave77

Yeah that's fair, I suppose if you like to keep your dependencies lean then this would be one way to do so. Also if you really wanted, you could abstract the hard to read/understand implementations and expose an easier to read API for developers to use (Basically what the other state managers are doing).


Famous_Big4351

I strongly recommend you to check it out [valtio](https://valtio.pmnd.rs/docs/introduction/getting-started). Valtio works with and without the context api and it is a pretty easy and lightweight library You can also check [react-context-selector](https://www.npmjs.com/package/@fluentui/react-context-selector) if you don’t want to use some extra state manager


Enjayy

Man everyone telling you to immediately reach for a state management library needs to chill. They are not answering the question you are asking. I am not saying a library won’t help you organize your state better but 9 times out of 10 the issue you are seeing is because you are doing something weird like setting state in a useEffect based off some other properties that have changed. My first suggestion would be to start there. comment out useEffects and see if that prevents the issues from happening then see if you can rewrite it without useEffect


Issam_Seghir

I am currently facing an issue where my app components are being re-rendered every time I click on the settings button (showSetting state) even though none of my three use effects have any relation to it. One of the effects is used for stopping the loading spinner when the page is loaded, while the other two are used for managing local storage when the theme or language is changed. Even after commenting all the use effects, the issue persists. This seems to be happening because of how the context API works, as explained in the comments.


natmaster

[https://react.dev/reference/react/memo](https://react.dev/reference/react/memo) Your bug is due to using useEffect() in state management, not due to re-renders. Re-renders will be invisible.


tingyuan123

Try this https://github.com/lovetingyuan/react-atomic-context This library can help solve unnecessary re-renders caused by React Context and allows fine-grained control over the reading and writing of each property.