I've got a simple React component that I connect up (mapping a simple array/state over). To keep from referencing the context for store I'd like a way to get "dispatch" directly from props. I've seen others using this approach but don't have access to this for some reason :)
Here are the versions of each npm dependency I'm using currently
"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"
Here is the component w/ connect method
class Users extends React.Component {
render() {
const { people } = this.props;
return (
<div>
<div>{this.props.children}</div>
<button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
</div>
);
}
};
function mapStateToProps(state) {
return { people: state.people };
}
export default connect(mapStateToProps, {
fetchUsers
})(Users);
If you need to see the reducer (nothing exciting but here it is)
const initialState = {
people: []
};
export default function(state=initialState, action) {
if (action.type === ActionTypes.ADD_USER) {
let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
return {people: newPeople};
}
return state;
};
If you need to see how my router is configured w/ redux
const createStoreWithMiddleware = applyMiddleware(
thunk
)(createStore);
const store = createStoreWithMiddleware(reducers);
var Route = (
<Provider store={store}>
<Router history={createBrowserHistory()}>
{Routes}
</Router>
</Provider>
);
update
looks like if I omit my own dispatch in the connect (currently above I'm showing fetchUsers), I'd get dispatch free (just not sure if this is how a setup w/ async actions would work usually). Do people mix and match or is it all or nothing?
[mapDispatchToProps]
While you could pass
dispatch
down as part ofdispatchToProps
, I would recommend avoiding accessing thestore
ordispatch
directly from within your components. It seems like you would be better served by passing in a bound action creator in connect's 2nd argumentdispatchToProps
See an example I posted here https://stackoverflow.com/a/34455431/2644281 of how to pass down an "already bound action creator" this way your components don't need to directly know about or depend on the store/dispatch.
Sorry to be brief. I'll update w/ more info.
You can usually mix and match based on what you'd like.
You can pass
dispatch
on as a prop if that is what you want:I'm not sure how
fetchUsers
is used (as an async function?), but you would usually use something likebindActionCreators
to auto-bind dispatch and then you would not have to worry about usingdispatch
directly in connected components.Using
dispatch
directory sort of couples the dumb, stateless component with redux. Which can make it less portable.By default
mapDispatchToProps
is justdispatch => ({ dispatch })
.So if you don't specify the second argument to
connect()
, you'll getdispatch
injected as a prop in your component.If you pass a custom function to
mapDispatchToProps
, you can do anything with the function.A few examples:
To save you some typing Redux provides
bindActionCreators()
that lets you turn this:into this:
or even shorter when prop names match action creator names:
If you'd like you can definitely add
dispatch
there by hand:There's no official advise on whether you should do this or not.
connect()
usually serves as the boundary between Redux-aware and Redux-unaware components. This is why we usually feel that it doesn't make sense to inject both bound action creators anddispatch
. But if you feel like you need to do this, feel free to.Finally, the pattern you are using right now is a shortcut that's even shorter than calling
bindActionCreators
. When all you do is returnbindActionCreators
, you can omit the call so instead of doing this:can be written as this
However you'll have to give up that nice short syntax whenever you want something more custom, like passing
dispatch
as well.