Skip to content

Commit

Permalink
Accept object as valid mapStateToProps argument
Browse files Browse the repository at this point in the history
  • Loading branch information
josepot committed Mar 8, 2017
1 parent ff33f0c commit 12fcc4c
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 33 deletions.
4 changes: 3 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ It does not modify the component class passed to it; instead, it *returns* a new
<a id="connect-arguments"></a>
#### Arguments

* [`mapStateToProps(state, [ownProps]): stateProps`] \(*Function*): If this argument is specified, the new component will subscribe to Redux store updates. This means that any time the store is updated, `mapStateToProps` will be called. The results of `mapStateToProps` must be a plain object*, which will be merged into the component’s props. If you don't want to subscribe to store updates, pass `null` or `undefined` in place of `mapStateToProps`. If `ownProps` is specified as a second argument, its value will be the props passed to your component, and `mapStateToProps` will be additionally re-invoked whenever the component receives new props (e.g. if props received from a parent component have shallowly changed, and you use the ownProps argument, mapStateToProps is re-evaluated).
* [`mapStateToProps(state, [ownProps]): stateProps`] \(*Function* or *Object*): If this argument is specified, the new component will subscribe to Redux store updates. This means that any time the store is updated, `mapStateToProps` will be called. The results of `mapStateToProps` must be a plain object*, which will be merged into the component’s props. If you don't want to subscribe to store updates, pass `null` or `undefined` in place of `mapStateToProps`. If `ownProps` is specified as a second argument, its value will be the props passed to your component, and `mapStateToProps` will be additionally re-invoked whenever the component receives new props (e.g. if props received from a parent component have shallowly changed, and you use the ownProps argument, mapStateToProps is re-evaluated).

If an object is passed, each function inside it is assumed to be a Redux selector.

>Note: in advanced scenarios where you need more control over the rendering performance, `mapStateToProps()` can also return a function. In this case, *that* function will be used as `mapStateToProps()` for a particular component instance. This allows you to do per-instance memoization. You can refer to [#279](https://github.com/reactjs/react-redux/pull/279) and the tests it adds for more details. Most apps never need this.
Expand Down
26 changes: 26 additions & 0 deletions src/connect/mapStateToProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@ export function whenMapStateToPropsIsFunction(mapStateToProps) {
: undefined
}

function getSelectorFromObject(objectSelectors) {
return function (state) {
const result = {};
Object.keys(objectSelectors).forEach(function (key) {
result[key] = objectSelectors[key](state);
});
return result;
};
}

function isValidmapStateToPropsObj(mapStateToProps) {
return typeof mapStateToProps === 'object' && Object
.keys(mapStateToProps)
.map(function (key) { return mapStateToProps[key] })
.every(function (val) { return typeof val === 'function'; });
}

export function whenMapStateToPropsIsObject(mapStateToProps) {
return (isValidmapStateToPropsObj(mapStateToProps)) ?
wrapMapToPropsFunc(
getSelectorFromObject(mapStateToProps), 'mapStateToProps'
) :
undefined
}

export function whenMapStateToPropsIsMissing(mapStateToProps) {
return (!mapStateToProps)
? wrapMapToPropsConstant(() => ({}))
Expand All @@ -14,5 +39,6 @@ export function whenMapStateToPropsIsMissing(mapStateToProps) {

export default [
whenMapStateToPropsIsFunction,
whenMapStateToPropsIsObject,
whenMapStateToPropsIsMissing
]
Loading

0 comments on commit 12fcc4c

Please sign in to comment.