Why does react context needs a provider? - reactjs

Context state can just be an observable and update components who subscribe like the observer pattern.
If you need the context state in a component just subscribe to a specific context.
Why do we need to render the context provider at the root of the app in order to use it somewhere else?
I ask since i see many libraries and apps use context now as the main way to share state between components but I don't understand the need to render the provider at the root of the app since each shared state (context) could be initialized outside of render functions
I made an npm package that does something similar in order to simplify the context/shared states of an app as an example of what i mean
https://www.npmjs.com/package/jstates
And a package for react bindings
https://www.npmjs.com/package/jstates-react

The reason is IMHO is recat tries to follow a paradigm where you don't have global state.
In general you want state to be as local as possible.
This allows better testing where you can feed mock state into the provider easily.
If you have a global object where everyone subscribe to it would be unclear where state is coming from.
With the context provider it very clear and state is encapsulated inside the component tree (no global objects).

Context API has to support multiple instances of the same context provider (e.g. while migrating part of the project to a new version of some library).
Even if libraries that use Context are most often used as singletons (for managing global state), when Thinking in React, authors need to support composable Components, not just global singletons. React API design also prefers Components over other patterns when feasible (e.g. <Suspense /> and <Provider />, but not life cycle hooks).
When designing support of multiple instances, some pattern for inversion of control is advisable for easier debugging (more constrains == less things that could go wrong).
Thus, explicit visibility in the React Components tree is preferred (notice that even life cycle methods and hooks are visible in the tree node details - but you only need to see those for a single node, not to identify "all children that have access to this context").

Related

What "data" should you pass with React context

The React doc's say that context is for passing data around without prop drilling
I get that usually that "data" will be some kind of state.
What other kind of data might you want to use context for?
Specifically, we have a service layer object that has a bunch of methods to interact with APIs and external libraries. Is there any benefit of wrapping these objects in context?
They seem to work fine just accessing them like any regular import but colleagues are saying they should be wrapped in context.
Context is useful to share data that won't often change across component avoiding props drilling.
For instance, let's say you have a modal component and you want to be able to control the open state of your modal in many components, you may want to provide a context for your modal component (that what react-modal)
For your question about benefits of wrapping services in contexts there is no real answer, it depend of your project structure and your state management,
if you're request consume context based data (token, cache or ids) why not but if you use other state management system and your services relies on it, I would say there is no reason to wrap your services in context.

Singleton or React Context to access data access layer functions?

In React what’s the best approach to pass around an instantiated class that provides access to backend data functions (eg getXX, createXx). In terms of:
A) singleton
B) react context
Does React Context provide some benefit? If using React Context where would you instantiate the class and add it to the Context?
Note: was intending to define data access class as an interface, then could have Dev and Prod implementations I could manually swap in/out.
I don't think there's an absolute answer to this, but my thoughts are that you should have it as react context only if it depends on react state.
In other words, if you want the behavior of the API call to function differently when you're in this or that particular state, then having it as context makes sense. If it's independent of that, there's no harm in having it be a singleton.

Redux and React context together

I am building a web app where redux is configured and app is fairly large.
Now I want to store some user preferences which will be available as part of an API respopse.
As this data is required to the majority of components I am planning to store data in the context and wrap application using the context.
I have Few questions regarding approach.
Will considering context impact the performance?
As Redux is already configured which internally uses the Context. So should we continue to use redux for user data.
Is it good practice to use Redux and Context together.
Context and Redux are very different tools that solve different problems, with some overlap.
Context is not a "state management" tool. It's a Dependency Injection mechanism, whose only purpose is to make a single value accessible to a nested tree of React components. It's up to you to decide what that value is, and how it's created. Typically, that's done using data from React component state, ie, useState and useReducer. So, you're actually doing all the "state management" yourself - Context just gives you a way to pass it down the tree.
Redux is a library and a pattern for separating your state update logic from the rest of your app, and making it easy to trace when/where/why/how your state has changed. It also gives your whole app the ability to access any piece of state in any component.
In addition, there are some distinct differences between how Context and (React-)Redux pass along updates. Context has some major perf limitations - in particular, any component that consumes a context will be forced to re-render, even if it only cares about part of the context value.
So, yes, you can use them both in the same app, in the same way you can use a hammer and a screwdriver together on the same construction job.
For more details, see my posts:
Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
React, Redux, and Context Behavior
A (Mostly) Complete Guide to React Rendering Behavior
Will considering context impact the performance?
Since you want to share user preferences that (I guess) do not change often, you could use a React context to share that data.
But performance issues arise when you put multiple different data in one React context that update at different rates. This is because every component that uses the context will be rerendered even if the part of the context it is interessted in did not change. In this case you can split the context and use one context for each part of the data.
Since you want to use the context to share an application state, you should use Redux. In Redux you use selectors to select a part of the application state. This useSelector hook is implemented in a way that it only triggers a rerender of the component if the selected part changes. You can even pass it an equality function if you want to change the way state change is detected.
As Redux is already configured which internally uses the Context. So should we continue to use redux for user data.
I would say: yes, continue with Redux.
Since you already use Redux you should not spread your application state management over different concepts. Put the user settings in the Redux store (like any other application state) and don't handle them special.
Is it good practice to use Redux and Context together
Well, Redux is based on the React context. So if you use Redux it is already a good practice.
If you mean using both for application state management, I think you should go the Redux or the React context way. Mixing them makes it harder to understand where state is managed.

Global context for bit-tracked React component

I'm developing a React component library for a web site. For local development I use Storybook. I think bit can be a good tool (better than npm link) for exporting library components and import them into the web site repo. Now the problem is that I'm using global context for some components but bit components must be isolated and self-sufficient. I don't want to wrap all my tiny components that use global context only to render them on bit.dev!
I have been able to resolve the same problem with storybook using decorators. So, I define a component without wrapping it with a ContextProvider and then in the stories file I use a decorator that wraps my component with the ContextProvider.
Is there a way to wrap bit components with global context provider without wrapping the actual component that will be used in production web site where a single global context provider wrap the entire app? What about best practices about this kind of workflow?
Using global context when implementing reusable components is not recommended.
Not only when using Bit, but when another project consumes a component it needs to have the same exact context for the component to work. Making the component less reusable and attractive to consumers.
The fact that this is not comfortable for rendering examples on the playground in bit.dev is a side-effect for it.
What you can do is either decouple the state from the component and use the params to get state and actions directly, via APIs. Or you can encapsulate the state inside the component.
You can read more about it in Bit's best practices for building reusable components - https://docs.bit.dev/docs/best-practices#state-managers
and also here - https://github.com/Tallyb/reusable-components-styleguide#globals

React components with shared state that are far away

I am new to React so please excuse me if this is a noob question but I really could not find the answer in the DOCs or elsewhere.
Let's say I have two buttons with a counter that share the state but are far away from each other in terms of the placement in the UI.
The documentation says the common owner component for both buttons should own the state. It makes sense if the components are next to each other like in the example but what if my buttons are each part of a different UI group and are far away in terms of nesting? My state holder would be the root of the document and I would have to pass a handler function down through many layers. And what if I need to add new component somewhere else that also needs to know the state? Would I have to modify all the parent components in the way to pass the state down? That is tremendously impractical.
Without React I would have some global Subscribe/Publish pattern like jQuery Observer and all UI elements could subscribe/publish to it regardless of their nesting position.
How does React solve this?
Related question: If I need to load/save the state to DB, how do I pass a reference of the controller (or Whatever) to each React component that stores the state?
1 for global state you may use REDUX
Redux is a predictable state container for JavaScript apps
for connect/subscribe component with that state ,you should use react-redux
If components are far away in terms of nesting, you may connect/subscribe them to redux store, and take only neccessary part of state. They will update if only neccessary part is changed.
article that explains how you can do your case
to learn how to use redux you can watch this videos from creator of redux (Dan Abramov)
1.getting-started-with-redux
2.building-react-applications-with-idiomatic-redux
3.I definitely recommend to you discordapp rectiflux channel. because you allways can ask any question online.(there you can find contributors of that tools)
2 alternative way that less verbose then redux is MobX
MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP). The philosophy behind MobX is very simple:
Anything that can be derived from the application state, should be derived. Automatically.
I suggest to look at the Flux stores. In short, stores are like model in your application. You can listen to change (subscribe) and also modify their properties (publish). You can see how it was done in example app.
A better option is to go with Redux.
Redux is enabling use cases like yours in a way simpler fashion :)
It will help you with all the state and make your life much easier.
Some good resources for learning:
The Redux Website
Video courses from Dan Abramov, the creator [Free]
Awesome course on Udemy [Not free]
Building Applications with React and Redux in ES6
And finally take a look at this youtube series [Free]
Managing state in the middle layers of your app should be avoided where possible. This data belongs in a store, which holds the global state of the app. Then each component accesses the state via its props.
The naïve approach to get the data down to the component is to pass the store through all the layers of your app "manually", i.e. through props.
Smarter alternatives exist, which use connected components, that access the global state through the context (as opposed to the props). Typically, the presentational component (your button component) is wrapped in a container component that handles this connection to the store, then passes the data in via props.
There are numerous frameworks that facilitate this process, links to which are already provided in the other answers.
If you are trying to share simple states, try this ( I am the author): react-provide-state
Otherwise I will recommend Redux. It has become the most popular tool for managing application states.
In the applications being working on, we use Redux to manage the main application states and almost all other states. But we use 'react-provide-state' for simple, UI only states like Modal, Checkbox states.

Resources