What "data" should you pass with React context - reactjs

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.

Related

is there any use case for context api if an app already uses a tool like redux?

I'm not aware of any use case for using Context API if an app already uses a tool like Redux. Seems like Context API would only be useful for something quick and dirty where performance wasn't critical and the developer didn't know Redux. Does this seem like an accurate assertion? Ie if an app is already implementing Redux then there's no additional use case which would justify the use of Context API?
"Is there any use case to use context api if redux is already in place for an app?"
Yes, there is/are. Context API is a mechanism used to share data (including state) between React Components. Redux is a State Management tool.
You can have both Redux (for managing state) and Context sharing data (different from Redux state) between Components.
Here's a real life open source React app using both Redux and Context API at the same time.
Recommended reading: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
The Context API allows you to pass a value down from any component (anywhere in the tree) to all of its descendents. Redux manages a single global state. This is completely different.
Here is a concrete example where you need the Context API even though you are using Redux: let's say that you are designing a timeline-like page containing many Posts (each post having an id allowing you to look it up in the Redux store), and each Post component contains a lot of sub components, to show for instance the title, the content, the likes, the comments, the tags, etc.
All of these sub components need access to the post id in order to get the right data from the Redux store. You could pass it directly from the parent Post component to all of the children (and grandchildren, etc), but this may get annoying, so rather than prop-drilling you can instead wrap each Post in a Context with the post id as a value, and then all of the children and grandchildren can use the context value directly without any prop-drilling.
There is no way you can solve this problem with Redux, because it relies on having separate contexts for each post.

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.

Why does react context needs a provider?

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").

Passing down props in a React library invisible to the app using the library

I am developing an open source library to use the Ionic framework with React (it normally works with Angular): https://github.com/pors/reactionic/
This React-Ionic library can be used by developers to create mobile apps. These apps will have their own way to keep state in their app, either by passing down props through composition, or using Flux/Redux, etc.
The React-Ionic library also needs to keep state for a number of things. For example, the "Body" component that wraps all contents needs to know if the content contains "Tabs". So the "Tabs" component needs to be able to change the state in a higher-up component.
I currently use composition to do this, but this has the disadvantage that the app developer needs to pass on props that are specific to the React-Ionic library. I want these props to be invisible for the developer.
What is the "React way" of solving this? I can think of two things, please let me know what the best solution is:
Use context.
Use Flex/Redux just for the library. Is this possible? Won't it interfere with the "state management" used by the app?
Otherwise?
I have added an image that hopefully clarifies what I try to accomplish:
So I want to pass state information down from the IonBody component to the IonTabs component, without the "App component" having to pass props down. And similarly, the IonTabs component should be able to call an IonBody function.
Thanks!
1) If you want to pass props down so they "fall through" to a child component, you can use the JSX spread operator, which will merge in old props:
<Component {...this.props} more="values" />
2) Context is an experimental feature and shouldn't be used unless in a very specific few cases; it essentially lets you create a "falling leaf" outside the state tree you create w/ props. This can lead to very unexpected results since it is generally outside the React/Flux paradigms. There are a few use cases for it, but they're generally only as last-resorts or only with very specific rationale
3) With one-way data flow, you generally want to use something like Flux/Redux for your state management. Child components don't get to really know about their parents, and vice versa. They communicate via props (and only top-down, really), so actions need to go "back to the top" of the state tree and propagate down from there.
As a last note, I wonder if you might consider React-native over React-ionic. It's going places IMO and is probably the ideal choice for taking a React app native. Just a thought :)

Where should be the line to separate stateful and stateless component in React?

React encourages the use of stateless components as much as possible and have a stateful parent component managing them.
I understand that this can make the stateless components more reusable, and easy to manage.
However, to the extreme, we can always put the state at the top level component, like App.js, and pass down information and callbacks through a long props chain. And if using Flux, the actions can always be dispatched in it too (executed through callbacks).
So I'm wondering what's line to separate stateful and stateless components? And if using Flux, where should the Actions to be dispatched?
--- Add an example ---
Say I have a google docs like web app that have a tool bar and displayed content. I imagine we will have the component structure.
<App>
<Toolbar />
<Content />
</App>
The tool bar has buttons that will affect the display content, say the bold text button.
So should the App pass down onButtonPressed callback props to Toolbar and dispatch Actions in itself, or should let the Toolbar to do it itself?
Should the App pass down contentString props to Content, or let Content itself listen to Store changes?
Thanks!
From my point of view, a simple application could use the pattern of Flux in that way :
Children emit actions.
The application listens to stores and propagates processed data to his children.
With that approach, you have the stateless component, but with a good code organisation without the callback props. But both of your propositions are also correct, it's a decision that you make regarding the size and needs of your application.
If the component that you build will be used outside of your application, don't use flux as much as possible and let the developer choose the wanted approach for his needs.
It's a good question, and it is being solved differently even between different Flux implementations.
I prefer having my state in one high-level component, that sees the "big picrure", and propagate data using props to all the low-level ones. In a good React app, most of the components shouldn't "care" where the data is coming from.
Having a one good structured model instead of several fragmented ones also proves itself to be beneficial so far. (by the way, that can be achieved even using several stores, the high-level component could listen to all of them, and virtually "hold" this big model).
Regarding actions - I prefer having all my "dumb" visualization/ui/display components work with callback props. That way it is easier to re-use them, and it is a good separation of concerns.
In richer components that hold a bit of business logic, I call Reflux actions directly. Usually those are also container components themselves to aforementioned "dumb" ui controllers.
So bottom line - data should flow from as high as possible, actions can be fired from lower components, but always check whether you can achieve the same result with callback props.
To your question - the Toolbar is a complex enough component to have ToolbarActions of its own and call them directly. But the Content component should definitely get its data from above. It's also easier to reason the data flow that way, when the app gets complicated.
Hope that helps. The whole Flux thing is still an art in progress...

Resources