Community JavaScript Snippet
The mapStateToProps / mapDispatchToProps Cheatsheet I Wish I Had In 2018
Every React + Redux codebase from before hooks revolves around connect. Three accordions of the wiring I keep paged in for inheriting one of those repos.
The mapStateToProps / mapDispatchToProps Cheatsheet I Wish I Had In 2018
Every React + Redux codebase from before hooks revolves around connect. Three accordions of the wiring I keep paged in for inheriting one of those repos.
By @milozhang
May 2, 2026
·
Updated May 20, 2026
722 views
8
4.2 (9)
The mental model that finally made connect click for me: think of the connected component as a function of (ownProps + storeSlice + boundActionCreators) -> reactTree. mapStateToProps projects the store down to the slice this view cares about, mapDispatchToProps builds action creators that already know how to call dispatch, and the merged object is what the component sees. The view is a pure function of those merged props, exactly like a hook-based component is a pure function of useSelector plus closed-over dispatchers. The optimisation that connect adds is a shallowEqual check on the produced state-props: the wrapped component only re-renders when one of the projected fields actually changed, which is the entire performance story for large connected apps.
The shorthand is what I write nine times out of ten. connect(mapState, { fetchUsers, deleteUser, userSettings })(Users) is roughly a third the line count of the function form, and the resulting props (fetchUsers(), deleteUser(id), userSettings(opts)) read like the actions they describe instead of like dispatch indirection. The cost is that you cannot access ownProps or getState() inside the dispatcher; if you need to read a route param to build the action, you have to drop back to (dispatch, ownProps) => ({ ... }). The other gotcha is that thunks (functions returned from action creators) still work in the shorthand only because the bound dispatcher passes the function through to store.dispatch, which redux-thunk recognises; without that middleware the thunk would just become a noop action.
The order I always have to look up: compose(withRouter, connect(...)) is what you want, not the other way around. The outermost HOC runs first at construction time, but the innermost HOC sees the most enriched props at render time, which is what makes router-aware mapStateToProps possible. Concretely: withRouter injects match, history, location onto ownProps; connect then runs mapStateToProps(state, ownProps) and can read ownProps.match.params.route to look up the right store slice. The wrong-order example at the bottom is the bug I have shipped before: a per-route counter that always reads state.byRoute[undefined] and the team spends an afternoon wondering why the dashboard shows zero. compose is the same right-to-left composition Redux exports as a utility; it is just (f, g, h)(x) => f(g(h(x))).
