How can I access the Redux store from a function? - reactjs

I am creating a React components library that exports a TypeScript function that another app can use. In that function, I need to retrieve some information from the app's store. How can I do this?
I cannot import the store and do store.getState() since I wouldn't know where the app's store is. Is there a way I can use connect() to do it?

If it's possible to design your function as a custom React hook, then you can use useSelector() inside it.
If it's not feasible, than shaping arguments to expect store been passed in - is a way. Especially if you are going to target older versions of react-redux, without useSelector

Related

Is Redux internally using context API?

I had an interview, where the interviewer asked me if redux uses context API internally. Pls provide a detailed description if yes. Thanks
Redux doesn't use context api, it's a javascript library for state management. You can use Redux with any application- like (react, angular, vue, svelte, etc). However, for using redux with react applications, you need react-redux which is the official react bindings for redux.
react-redux uses React's context api to make the redux store accessible to all components. The reason why you need react-redux is because, React uses virtual dom - which means you can't manipulate the DOM directly. In other libraries like angular, we use the NgRx library (For angular).
Internally, React Redux uses React's "context" feature to make the
Redux store accessible to deeply nested connected components. As of
React Redux version 6, this is normally handled by a single default
context object instance generated by React.createContext(), called
ReactReduxContext.
Source
Yes, but differently than if you would be doing it by yourself.
If you were to use Context manually, you would usually do value propagation - passing the current state value down the tree. This can lead to very inefficient rerendering behaviour. See this article for a deeper explanation.
React-Redux on the other hand uses context for dependency injection. The store is passed down the tree and will never change, never triggering a rerender. All the rest is done by Redux internally, using manual subscriptions. This is much more performant.

Is there a way to access Context in a Redux Thunk?

This is more of an understanding question and I also want to know the community thoughts, rather than a code question.
We have a React App using redux for managing the global store and redux-thunk for dispatching actions. Now we want to localize the App and add a language switch. For that purpose I created a HOC which uses React.Context to store the dictionary for current language in it. And I wrapped all Components in this HOC - everything works just fine.
But we also need to access to the dictionary in the thunks to e.g. provide success/error messages after API calls in the selected language. It seems to be impossible without passing dictionary into thunks.
I've read a lot about Context API and when to use it and that it has different purpose than Redux. That's why I put the translations in the Context and not in the store, mainly for this reason. But now I'm getting the feeling that I missed something and should actually put the translations in the store instead to not be forced to pass the dictionary to the thunk every time I need it there. Is it so?
Or is there a way to implement something like getContext similar to getState from redux-thunk?

Connect a helper function to react-redux store

I exposed a bundle of helper functions in helpers.js , is there a way that I can make all my functions in helpers.js aware of the redux store?
I understand normally if its in a class Component, I could use export default connect(mapStateToProps)(ComponentName) so that state is mapped to my props.
I'm also trying to avoid direct access from redux.store or expose store globally.
This is not a duplication of React Redux - accessing existing store in a helper function
solution to the answer exported store, which I don't have control of that.
Thanks for helping.

using connect's mapToProps vs reading and dispatching to the store as a global?

What's the difference between A) using the connect method of connecting state and dispatch function to a component and B) simply having functions in a component that do the dispatching as well as accessing the store as a global directly?
(Not ES2015)
Quoting from the Redux FAQ on importing the store directly:
While you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.
I also recently wrote a Reddit comment on why you should use React-Redux and connect instead of talking to the store directly. Quoting that:
First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.
Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.
Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.
Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.
And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.
For more info, see:
The Redux FAQ section on performance
The Redux FAQ entry on connecting multiple components
The Redux FAQ entry on components re-rendering too often
The Redux FAQ entry on importing the store directly
The Redux Performance section of my React/Redux links list
And finally, my blog posts Practical Redux, Part 6: Connected Lists, Forms, and Performance and Idiomatic Redux: Why use action creators?.
Source: I'm a Redux maintainer, and author of the Redux FAQ.

What's the relationship between <Provider> and connect() in React-Redux?

I'm brand new to Redux and I'm trying to figure out the relationship between <Provider> and connect().
As I understand it, connect connects your component to the store. However, nowhere in the function arguments do you tell connect where exactly that store is!
If I'm not mistaken, the store is automagically provided to connect() by the <Provider>. This to me seems very counter-intuitive, because the entire point of Redux is to be transparent.
So my question is, how does <Provider> pass the store off to connect() without using some sort of global variable? Does it traverse the entire tree, searching for connected components and then inject itself? Is that not inefficient? And if so, how would I use two different stores within the same component tree?
Secondly, supposing I don't want to use <Provider>, how can I use connect() without it? i.e., how can I explicitly pass a store to each connected component?
<Provider> and connect are part of the react-redux module. They work together, you shouldn't really use one without the other. You can use redux on its own without react-redux, but you'll probably end up re-creating some or all of the features that react-redux provides.
react-redux works by using the React context. Context is like a hidden layer for passing variables that are shared by multiple components without explicitly passing them. To use context, you need to set the context somewhere, but also, any component that wants to use something from the context needs to get the variable. In react-redux <Provider> essentially saves the store to the context and connect provides a way to get the store from the context.
If you haven't already, I recommend these videos for getting started with Redux and react-redux from the creator of Redux.
The redux docs are pretty great and have some information regarding Provider and connect()
The option we recommend is to use a special React Redux component
called <Provider> to magically make the store available to all
container components in the application without passing it explicitly.
You only need to use it once when you render the root component
Essentially it leverages the use of context which is from React. As per the docs this allows you to pass data through the component tree without having to pass the props down manually at every level.
There's no reason why you can't explicitly pass the store. The idea here is that it just makes things easier.

Resources