Singleton or React Context to access data access layer functions? - reactjs

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.

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.

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.

Singleton Class vs Statemangement tool like Redux for App State

Can somebody explain to me why you would ever use a statemanagement tool like Redux or the Provider library instead of just creating your own Singleton class to hold the state of your application?
Redux is so much more than a singleton. It gives you pub/sub, time-traveling to prior states (especially good for debugging) and an open-ended api to plug in your own functionality. It is an especially good place to handle side effects.
In react, you can't just "plug in" your own data structure and expect everything to update properly. React updates on an as-needed basis. In order to do that, you have to use the React api in one form or another (context api, hooks, etc.).
Any singleton implementation you do will essentially be a subset of redux's functionality. In an overwhelming majority of cases, you will need all of redux's features (along with 3rd party middlewares) in a long-term production application.

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

what is a generally acceptable way to structure a service layer in a reactjs project?

I'm using axios.get() to call an api endpoint in one of my components. I need the ability to encapsulate this endpoint call so I can reuse this implementation by calling it from several different components.
What is a generally acceptable way to structure this type of implementation in a React project? For example, would it be generally acceptable to group related api calls into js files in a src/services directory at the same level as src/components?
It would be acceptable to create a utils or services directory and group related API calls. However it is important to remember that with async requests you need to consider the components calling the api service utils might un-mount. This might result in warnings or errors if not handled properly. A possible way to handle this might be to only execute callback functions if component is still mounted tracked via a state variable in a useEffect hook.
A more modern react approach might be to leverage hooks and react context for data handling. You could create a DataContext with a useReducer hook to fetch or push data for example.
(see https://reactjs.org/docs/context.html)
There are many way to do this.
Redux. It's old way is that you need to use redux style.
Hooks. Starts from React 16.8 version.
I will recommend to you use hooks. It's more useful and guarantee true way.
3 years ago i lived in Redux paradigm and every time write the monkey code thinking about consistent Redux store state.
Please try this one react-async package.

Resources