-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add v6 related info to Quick Start * Remove doc regarding directly passing store * Add doc passing `context` to `<Provider />` * Add docs around accessing store with v6 * Rework "Accessing Store" content Reordered sections Added explanation of internals and warning note * Remove context content from "Quick Start" * Copy CSS changes from main Redux site
- Loading branch information
1 parent
5088345
commit 75b90f9
Showing
6 changed files
with
295 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
--- | ||
id: accessing-store | ||
title: Accessing the Store | ||
hide_title: true | ||
sidebar_label: Accessing the Store | ||
--- | ||
|
||
# Accessing the Store | ||
|
||
React Redux provides APIs that allow your components to dispatch actions and subscribe to data updates from the store. | ||
|
||
As part of that, React Redux abstracts away the details of which store you are using, and the exact details of how that | ||
store interaction is handled. In typical usage, your own components should never need to care about those details, and | ||
won't ever reference the store directly. React Redux also internally handles the details of how the store and state are | ||
propagated to connected components, so that this works as expected by default. | ||
|
||
However, there may be certain use cases where you may need to customize how the store and state are propagated to | ||
connected components, or access the store directly. Here are some examples of how to do this. | ||
|
||
## Understanding Context Usage | ||
|
||
Internally, React Redux uses [React's "context" feature](https://reactjs.org/docs/context.html) 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`. | ||
|
||
React Redux's `<Provider>` component uses `<ReactReduxContext.Provider>` to put the Redux store and the current store | ||
state into context, and `connect` uses `<ReactReduxContext.Consumer>` to read those values and handle updates. | ||
|
||
## Providing Custom Context | ||
|
||
Instead of using the default context instance from React Redux, you may supply your own custom context instance. | ||
|
||
```js | ||
<Provider context={MyContext} store={store}> | ||
<App /> | ||
</Provider> | ||
``` | ||
|
||
If you supply a custom context, React Redux will use that context instance instead of the one it creates and exports by default. | ||
|
||
After you’ve supplied the custom context to `<Provider />`, you will need to supply this context instance to all of your connected components that are expected to connect to the same store: | ||
|
||
```js | ||
// You can pass the context as an option to connect | ||
export default connect( | ||
mapState, | ||
mapDispatch, | ||
null, | ||
{ context: MyContext } | ||
)(MyComponent) | ||
|
||
// or, call connect as normal to start | ||
const ConnectedComponent = connect( | ||
mapState, | ||
mapDispatch | ||
)(MyComponent) | ||
|
||
// Later, pass the custom context as a prop to the connected component | ||
<ConnectedComponent context={MyContext} /> | ||
``` | ||
|
||
The following runtime error occurs when React Redux does not find a store in the context it is looking. For example: | ||
|
||
- You provided a custom context instance to `<Provider />`, but did not provide the same instance (or did not provide any) to your connected components. | ||
- You provided a custom context to your connected component, but did not provide the same instance (or did not provide any) to `<Provider />`. | ||
|
||
> Invariant Violation | ||
> | ||
> Could not find "store" in the context of "Connect(MyComponent)". Either wrap the root component in a `<Provider>`, or pass a custom React context provider to `<Provider>` and the corresponding React context consumer to Connect(Todo) in connect options. | ||
## Multiple Stores | ||
|
||
[Redux was designed to use a single store](https://redux.js.org/api/store#a-note-for-flux-users). | ||
However, if you are in an unavoidable position of needing to use multiple stores, with v6 you may do so by providing (multiple) custom contexts. | ||
This also provides a natural isolation of the stores as they live in separate context instances. | ||
|
||
```js | ||
// a naive example | ||
const ContextA = React.createContext(); | ||
const ContextB = React.createContext(); | ||
|
||
// assuming reducerA and reducerB are proper reducer functions | ||
const storeA = createStore(reducerA); | ||
const storeB = createStore(reducerB); | ||
|
||
// supply the context instances to Provider | ||
function App() { | ||
return ( | ||
<Provider store={storeA} context={ContextA} /> | ||
<Provider store={storeB} context={ContextB}> | ||
<App /> | ||
</Provider> | ||
</Provider> | ||
); | ||
} | ||
|
||
// fetch the corresponding store with connected components | ||
// you need to use the correct context | ||
connect(mapStateA, null, null, { context: ContextA })(MyComponentA) | ||
|
||
// You may also pass the alternate context instance directly to the connected component instead | ||
<ConnectedMyComponentA context={ContextA} /> | ||
|
||
// it is possible to chain connect() | ||
// in this case MyComponent will receive merged props from both stores | ||
compose( | ||
connect(mapStateA, null, null, { context: ContextA }), | ||
connect(mapStateB, null, null, { context: ContextB }) | ||
)(MyComponent); | ||
``` | ||
|
||
## Using `ReactReduxContext` Directly | ||
|
||
In rare cases, you may need to access the Redux store directly in your own components. This can be done by rendering | ||
the appropriate context consumer yourself, and accessing the `store` field out of the context value. | ||
|
||
> **Note**: This is **_not_ considered part of the React Redux public API, and may break without notice**. We do recognize | ||
> that the community has use cases where this is necessary, and will try to make it possible for users to build additional | ||
> functionality on top of React Redux, but our specific use of context is considered an implementation detail. | ||
> If you have additional use cases that are not sufficiently covered by the current APIs, please file an issue to discuss | ||
> possible API improvements. | ||
```js | ||
import { ReactReduxContext } from 'react-redux' | ||
|
||
// in your connected component | ||
function MyConnectedComponent() { | ||
return ( | ||
<ReactReduxContext.Consumer> | ||
{({ store }) => { | ||
// do something useful with the store, like passing it to a child | ||
// component where it can be used in lifecycle methods | ||
}} | ||
</ReactReduxContext.Consumer> | ||
) | ||
} | ||
``` | ||
|
||
## Further Resources | ||
|
||
- CodeSandbox example: [A reading list app with theme using a separate store](https://codesandbox.io/s/92pm9n2kl4), implemented by providing (multiple) custom context(s). | ||
- Related issues: | ||
- [#1132: Update docs for using a different store key](https://github.com/reduxjs/react-redux/issues/1132) | ||
- [#1126: `<Provider>` misses state changes that occur between when its constructor runs and when it mounts](https://github.com/reduxjs/react-redux/issues/1126) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.