Accessing the Store with React-Redux
Tags: react, redux, webdev, javascript
Published: 2021-01-25 01:50:01

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to access the Redux store with React-Redux.

### Accessing the Store

With React-Redux, we can access the store by defining a `mapStateToProps` function.

However, we can also access it in a customized way. Internally, React-Redux uses React’s Context API to make the Redux store accessible to deeply nested connected components.

Currently, React-Redux is normally handled by a single default context object instance generated by `React.createContext()` called `ReactReduxContext` .

`Provider` uses `ReactReduxContext.Provider` to put the Redux Store and the current state into context and `connect` uses `ReactReduxContext.Consumer` to read values and handle updates.

### Providing Custom Context

We can provide a custom context to React-Redux via the `context` prop.

For example, we can pass in our own context in the following code:

```
import React from "re
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";
function count(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}
const store = createStore(count);

function App({ increment, decrement, count }) {
  return (
    <div className="App">
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <p>{count}</p>
    </div>
  );
}
const mapStateToProps = state => {
  return { count: state };
};
const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const customContext = React.createContext();

App = connect(
  mapStateToProps,
  { increment, decrement },
  null,
  { context: customContext }
)(App);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store} context={customContext}>
    <App />
  </Provider>,
  rootElement
);
```

In the code above, we have the usual React-Redux code for connecting the store to the `App` component via `connect` .

However, we create a `customContext` via:

```
const customContext = React.createContext();
```

Then in the `connect` call, we have:

```
App = connect(
  mapStateToProps,
  { increment, decrement },
  null,
  { context: customContext }
)(App);
```

The 4th argument is `{ context: customContext }` , which is where we set our custom context.

Also, we have:

```
<Provider store={store} context={customContext}>
  <App />
</Provider>
```

to set our `context` prop via `context={customContext}` .

### Multiple Stores

We can also use multiple stores with React-Redux by nesting providers as follows:

```
import React from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore, compose } from "redux";
function countA(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    default:
      return state;
  }
}

function countB(state = 0, action) {
  switch (action.type) {
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}

const storeA = createStore(countA);
const storeB = createStore(countB);
function App({ increment, decrement, countA, countB }) {
  return (
    <div className="App">
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <p>{countA}</p>
      <p>{countB}</p>
    </div>
  );
}
const mapStateToPropsA = state => {
  return { countA: state };
};

const mapStateToPropsB = state => {
  return { countB: state };
};

const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const contextA = React.createContext();
const contextB = React.createContext();

App = compose(
  connect(
    mapStateToPropsA,
    { increment },
    null,
    { context: contextA }
  ),
  connect(
    mapStateToPropsB,
    { decrement },
    null,
    { context: contextB }
  )
)(App);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={storeA} context={contextA}>
    <Provider store={storeB} context={contextB}>
      <App />
    </Provider>
  </Provider>,
  rootElement
);
```

In the code above, we defined 2 separate stores by writing:

```
const storeA = createStore(countA);
const storeB = createStore(countB);
```

where `countA` and `countB` are the reducers.

Then we nest our `connect` calls within the arguments of the `compose` function to combine the connects as follows:

```
App = compose(
  connect(
    mapStateToPropsA,
    { increment },
    null,
    { context: contextA }
  ),
  connect(
    mapStateToPropsB,
    { decrement },
    null,
    { context: contextB }
  )
)(App);
```

We defined `mapStateToPropsA` and `mapStateToPropsB` to map states from the 2 stores before this call.

Then in the last argument of each `connect` , we pass in an object with the `context` that we want to use to connect the store to `App` .

Then in the `ReactDOM.render` call, we pass in:

```
<Provider store={storeA} context={contextA}>
  <Provider store={storeB} context={contextB}>
    <App />
  </Provider>
</Provider>
```

to set the `store` and `context` we want to use for each provider. The `context` prop of each Provider have to match with `connect` .

### Conclusion

We can access multiple stores by nesting multiple `Providers` and providing a store and context for each.

The context is defined by calling `React.createContext()` , which is part of the React Context API used to share data between components.

Then we can use the `compose` function to add combine multiple `connect` calls together. We pass into the 4th argument of `connect` in each call.

We can also use the same method to customize access to a single store, except that we don’t need to call `compose` .