How good is to apply React Context API for all screens - javascript

Currently I have four contexts that wrap all my routes (as shown bellow) so that I don't have lost providers all around my app screens and components. As far as I know, when I modify the value of a context variable, every component that uses it will update too, what can lead to memory problems, but my question is: if my providers, that wrap all routes/screens, even the ones that uses no context variable, may cause the same memory related problems.
<AuthProvider>
<SelectedBranchProvider>
<SelectedEventProvider>
<DrawerFormProvider>
<RightDrawerNavigator />
</DrawerFormProvider>
</SelectedEventProvider>
</SelectedBranchProvider>
</AuthProvider>

The danger with context isn't memory issues, it's unneeded re-renders. The way Context is implemented defeats some of React's diffing, so a change in Context can cause a re-render in any component that uses the same Context, even if the value that changes is unused in the component.
If you have a small app, or only rarely change what's in your context, you'll probably never hit these limitations. Good use cases for context are things that would require many re-renders and rarely change, like user language or app theme.
The docs for Context have a caveats section that goes over this: https://reactjs.org/docs/context.html#caveats
Here's a blog post with a good example of how this can cause re-renders: https://blog.logrocket.com/pitfalls-of-overusing-react-context/

Related

Does the React Context API replace the need for component props?

I've recently upgraded a React 15 project to use React 16.9. Specifically, I've completely replaced redux with the new Context API, pure functional components, and hooks. With the Context API, we also gain the ability for nested child consumers to obtain the data without having to pass it using props all the way through. However, I noticed that I don't have any component props anywhere as everything is passed via provider/consumer context.
So my question is does the context API make component props obselete?
I find people abuse redux and context. Btw, redux uses context internally.
To be honest, prop still should be your best friend in most of cases. Only when you want to avoid nested prop passing, you could then explore context where a provider is created as a parent, and then all deep down children can receive it as props.
Prop is still the way when children connect to the provider. The only difference is that these props are stored in a sort of "global" space now.
So in short, context doesn't replace prop, it still uses prop.
You have already answered your question. Context API avoids I quote one from react docs :
Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult
There is no other reason. If I want to reuse component or export it that depends context, user has no idea about it. Use cases like logged User, theme, or sone global state like work flow detail for the whole application etc, makes a good use case.

React Context vs Javascript window

React has a feature called Context which advertises a way to store globally accessible values without having to pass them down as props.
What is unclear to me is what advantages this has over storing values on the window. If on my page I have window.current_user = user_details, the user details are now available to all react components. What would the advantages be to moving this in to React's context?
If a variable on window changes, React won't know, so it can't re-render pieces of your app that depend on that data.
With context, any changes to the data will trigger re-renders.
There are arguably other advantages, but in my opinion, the re-render difference makes the two options basically apples and oranges.
On the other hand, Context isn't truly "global," because the Consumer (where you read the data) has to be somewhere beneath the Provider (where the values are written) in the hierarchy. This would make Context unsuitable, for example, in an app where the Settings menu was way down in the component hierarchy, but settings consumers were peppered throughout the app, as there's no way to pass values "up" using context.
So, if the data you're interested in doesn't change often (or at all) after the app's initial render, my opinion is that window could be more suitable than Context. Some folks will argue that this clogs up the window object, or that it violates other (usually sound) design principles, but in my opinion, if you understand the tradeoffs, using window can be a perfectly pragmatic decision.

Differences between require() and passing an object via prop or context

What's the difference between require()ing a singleton, and passing it down via React prop or context?
What are the use cases for each?
If you require() (or import) a module, you get the same object in any component.
Use modules for the code your component depends on:
Other components (Button).
Utility functions (getTextColor).
Global data storage (CommentStore).
The upside of importing a module is that it’s extremely easy to do, and you only need to do it once.
The downside of importing a module is that you can’t override what it points to. So, for example, you can’t easily swap out CommentStore or getTextColor modules in testing, or in a “living design guide”. Depending on your use case, this may or may not be a problem.
Passing something as a prop means you can pass a different thing every time.
Use props for inputs to your components that need to be customizable:
Data (comment).
Event callbacks (onClick).
UI properties (color).
The upside of using props is that they’re explicit and customizable. They’re primary mechanism of passing data down in React so when in doubt, use props.
The downside of using props is that sometimes you might end up passing a lot of props through intermediate components that don’t use them, just to get props down to the leafs. Normally this is fine in React because it trades some verbosity for ease of finding bugs. But in some cases it can get frustrating.
Context is an advanced API and should be used very sparingly.
It is likely that it will significantly change in the future.
Context is like implicitly passed props that become “global” for a subtree:
Theming (currentTheme).
Locale (currentLanguage).
Dependency injection (store).
The advantage over props is that you don’t need to pass them manually through every component. The advantage over importing is that you can override it from outside the component, which is handy for testing, server rendering, and for things that change.
The downside of context is that it has severe issues with updates, so don’t rely on its value updating correctly. For example, React Redux can safely pass store down because store itself never changes and has its own subscription mechanism.
In general we don’t suggest using context in your application code directly. It’s fine if some libraries use it because they will be easier to migrate when its API changes.
Finally, I’m not a natural painter, but here’s a doodle to sum it up:

Custom events versus callbacks in ReactJS

I'm new to ReactJS and I'm trying to figure out how to store and manipulate global state. For example, I'm writing an editor app that has some global state: selected color/background, active tool, current selection, etc.
I'm thinking about having a root interface component to store this information, and I'm ok with explicitly passing the state around using properties. I guess the idiomatic way for a children component to change global state is calling a callback received from the parent - personally I find this a bit annoying.
Instead, I'm firing custom events at the children and setting listeners on the parent. So far it is working really well, but I looked at a lot of sample code and never saw people using this pattern.
Is there any practical consequences I should consider?
Flux is great for manipulating global state because the Stores are globally accessible. Globals are known to be bad, but the way you interact with the Stores is through Actions. Actions make the state predictable and localized. So even though the state storage itself is global, Actions make the state interactions very local. At work we tend to do both reading & writing through Actions, so every state change is an "event" that leads to easily programmable behavior.
I really wouldn't compare Flux to Angular as their principles and flows are entirely different. Suggest you try Reflux.

Passing store state as props, or each component accessing global stores?

I am a bit confused by the statements: "Renders the whole application" and "Passing state to child components".
Example 1:
I have a todos app with a AppComponent and TodosListComponent. The AppComponent grabs the array of todos from the store and passes it as a property to the TodosListComponent.
Example 2:
I have a huge application with lots state. I have like 50 components building up my app. Do I want to pass all the state from the stores from AppComponent down through all the 50 components?
So I am wondering, what is the convention? It makes more sense to me to let individual components listen directly to the stores they care about. The advantage is that only individual components rerender, but why then the concept of "the whole application rerender on state change"?
What are the pros and cons of each? What is the common convention?
There are a few ways you can handle this. I think they're all valid and have their own trade-offs.
Get all the state and pass pieces of it to children
This is the technique you specifically asked about. Using this method, you'll have some function or method available to your top-level component that turns all the data from the stores into a "big bag of state" and then you'll selectively pass pieces of this data to child components. If those components have their own children, they'll pass it along as necessary.
The upside to this method is that it makes things generally easy to debug. If you have to change the way a piece of state is retrieved from a store, you only have to change it in the top-level component—as long as it gets passed down with the same name, the other components will "just work." If some piece of data is wrong, you should only need to look in one place to figure out why.
The downside to this technique what I call "props explosion"—you can end up passing a lot of properties around. I use this method in a medium-sized flux application, and a snippet of the top-level application component looks like this:
<section id="col-left">
<Filters loading={this.state.loading}
events={this.state.events}
playbackRate={this.state.videoPlayback.playbackRate}
autoPlayAudio={this.state.audioPlayback.autoPlay}
role={this.state.role} />
</section>
<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
<SessionVideo videoUuid={this.state.session.recording_uuid}
lowQualityVideo={this.state.session.low_quality_video_exists}
playbackRate={this.state.videoPlayback.playbackRate} />
<section id="transcript">
<Transcript loading={this.state.loading}
events={this.state.events}
currentEvents={this.state.currentEvents}
selection={this.state.selection}
users={this.state.session.enrolled_users}
confirmedHcs={this.state.ui.confirmedHcs}
currentTime={this.state.videoPlayback.position}
playing={this.state.videoPlayback.playing} />
</section>
</section>
In particular, there can be a lot of components between the top-level one and some eventual child that do nothing with the data except pass it along, more closely coupling those components to their position in the hierarchy.
Overall, I like the debuggability this technique provides, though as the application grew larger and more complex I found it was not idea to do this with only a single top-level component.
Get all the state and pass it as one object
One of the developers at Facebook mentioned this technique. Here, you'll get a big bag of state, just as above, but you'll pass the whole thing (or entire sub-sections of it) rather than individual properties. By utilizing React.PropTypes.shape in child components, you can ensure that the right properties are getting passed.
The upside is you pass way fewer properties around; the above example might look more like this:
<section id="col-left">
<Filters state={this.state} />
</section>
<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
<SessionVideo session={this.state.session}
playback={this.state.videoPlayback} />
<section id="transcript">
<Transcript state={this.state} />
</section>
</section>
The downside is that it becomes a little more difficult to deal with changes in the shape of the state; rather than just changing the top-level component, you'll have to track down everywhere that piece of data is used and change the way that component access the property. Also, shouldComponentUpdate can potentially become a little trickier to implement.
Allow components to get their own state
On the other end of the spectrum, you can grant application-specific (that is, non-reusable) child components to access the stores and build up their own state based on the store change events. Components that build their own state like this are sometimes called "controller-views" or, more commonly these days, "container components."
The upside, of course, is that you don't have to deal with passing properties around at all (other than change handlers and properties for more reusable components).
The downside, though, is that your components are more highly coupled to the stores—changing the stores or the data they provide (or the interface via which they provide that data) may force you to revisit the code for a larger number of components.
Also, as mentioned in the comments, this can potentially make server rendering a bit more difficult. If you only use properties (especially at only the top level), you can transport them more easily to the client and re-initialize React with the same properties. By allowing the stores to determine their own data, you need to somehow inject that data into the stores to allow the components to get that data.
A common approach, and one that I typically use now, is to make every component in your application only rely on props for global application state, and then decide if it makes more sense to (1) connect them directly to flux by wrapping them in a container, or (2) allow the props to be passed from some parent container.
There are abstractions that you might be able to use to make some of these techniques more viable. For example, a Facebook dev had this to say in a comment on Hacker News:
Now all your data is in stores, but how do you get it into the specific component that needs it? We started with large top level components which pull all the data needed for their children, and pass it down through props. This leads to a lot of cruft and irrelevant code in the intermediate components. What we settled on, for the most part, is components declaring and fetching the data they need themselves, except for some small, more generic components. Since most of our data is fetched asynchronously and cached, we've created mixins that make it easy to declare which data your component needs, and hook the fetching and listening for updates into the lifecycle methods (componentWillMount, etc).
Jason Bonta from Facebook explained the concept of "Containers" in his React.js Conf 2015 talk.
To summarize: containers are simply components that wrap other components, and take care of any data-related concerns such as talking to stores, while the underlying component is focused solely on the view (markup/styles/etc.) and doesn't care where the data comes from.
This makes the component
highly re-usable because it can be wrapped with a different container when data needs to come from a different place,
not contain irrelevant state, therefore easier to implement and optimize shouldComponentUpdate, and
using composition rather than mixins for this aligns with what is likely the future of React with ES6, which does not have idiomatic mixins.
UPDATE March 2019: Look into React Hooks. With hooks, you can accomplish the same goal as described above, but abstract data-related concerns, such as talking to stores, in re-usable chunks of code that can be applied to multiple components. The ReactConf talk React Today and Tomorrow and 90% Cleaner React With Hooks by Dan Abramov does a great job of explaining hooks, and how they are different from both mixins and past composition approaches.

Categories