Reputation: 6626
The store service from Redux is what ultimately utilized by various components in a React App. The methods (such as dispatch, getState and subscribe) exposed by it are used by all kinds components (like container or presentational).
I think the approach to pass this store service around is an important design decision. I see two approaches and they are:
1) By passing the store as a prop to every component at all nested levels. This is not the recommended one.
2) Use a tool like react-redux, which with the help of context, makes the store (state and dispatch to be exact) available wherever it is needed.
My questions are: Why not simply import the store wherever it is needed. For an SPA-based React App, store will be a singleton. Components nested at any level can simply import the store. Why should we adopt anyone of the above two approaches?
For a component at any nested level: Can we do this
import store from "path/to/store";
let MyComponent = () => {
let state = store.getState();
return (
<div onClick={() => {
store.dispatch({
type: "SOME_EVENT",
payload: store.somedata
});
}}>{state.dataINeedHere}</div>
);
};
export default MyComponent;
instead of
import { connect } from "react-redux";
let MyComponent = ({somedata, onMyAction}) => {
let state = store.getState();
return (
<div onClick={() => {
onMyAction(somedata);
}}>{somedata}</div>
);
};
const mapStateToProps = (state) => {
return {
somedata: state.somedata
}
}
const mapDispatchToProps = (dispatch) => {
return {
onMyAction: (input) => {
dispatch({
type: "SOME_EVENT",
payload: input
});
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
Upvotes: 2
Views: 4184
Reputation: 67449
The Redux FAQ covers this question, at http://redux.js.org/docs/FAQ.html#store-setup-multiple-stores.
Summarizing: while you can directly import a store, you're tying your code to that store implementation, which makes it less reusable and harder to test. Ideally, none of your own code actually ever references the store directly. Connected components, middleware, and thunked action creators all receive the relevant dispatch
and getState
function references by dependency injection, making them reusable and allowing easy mocking of behavior for testing.
Upvotes: 5
Reputation: 14276
Consider what happens when you have a second MyComponent, which manages data from a different part of the store. Your options are to tell each exactly how to access/update its data:
<Container>
<MyComponent path="/a/b/c" />
<MyComponent path="/a/b/d" />
</Container>
or you can give each access to only what it needs:
<Container>
<!-- context /a/b was passed to Container -->
<MyComponent data={c} onUpdate={update(c)} />
<MyComponent data={d} onUpdate={update(d)} />
</Container>
The latter makes the MyComponent much simpler and much more flexible.
Upvotes: 0