如何正确记住mapDispatchToProps?

时间:2017-08-03 23:19:21

标签: reactjs redux react-redux memoization

首先,这是我的HOC:

export default function connectField({
         nameProp = 'name',
         valueProp = 'value',
         dispatchProp = 'dispatch'
     }: ConnectOptions) {

    return compose(
        getContext(contextTypes),
        connect((state, ownProps) => {
            const path = [namespace,...getPath(ownProps),...toPath(ownProps[nameProp])];
            const value = getOr('', path, state);
            return {
                [valueProp]: value
            };
        }, (dispatch,ownProps) => { // <----------- mapDispatchToProps
            const path = [...getPath(ownProps),...toPath(ownProps[nameProp])];

            return {
                [dispatchProp]: value => dispatch({type: ActionTypes.Change, payload: {path, value}})
            };

        }, (stateProps, dispatchProps, {[FIELD_PATH]: _, ...ownProps}) => {
            return {...stateProps, ...dispatchProps, ...ownProps}; 
        }, {
            areMergedPropsEqual: (a,b) => {
                let eq = shallowEqual(a,b);
                console.log('areMergedPropsEqual',a,b,eq);
                return eq;
            },
        }),
        withContext(contextTypes, props => {
            return {[FIELD_PATH]: [...getPath(props), props[nameProp]]};
        }),
    );
}

中间有我的mapDispatchToProps。这导致areMergedPropsEqual每次都返回 false ,因为它每次都会创建一个新的动作创建者。

我无法弄清楚如何记住这一点:

value => dispatch({type: ActionTypes.Change, payload: {path, value}})

这样我每次都会返回相同的函数实例。

关于“每个实例的记忆化”有一些注意事项in the docs这是我想要的,但我不能完全理解我应该在这里做的事情。

要清楚,我知道如何记忆功能。但是,我不想使用具有无限历史的大缓存。这是不必要的内存消耗。我只需要像how reselect does it一样的缓存大小1。问题是我不能直接在connectField内创建“选择器”,因为它仍会创建一个共享实例 - 即,所有“连接字段”将共享相同的缓存,它们将相互覆盖,否定利益。它必须是每个组件实例这是针对React-Redux的connect方法。它有一个语法,以便您可以在正确的位置创建选择器,并且每个实例只会运行一次。我只是在解密API时遇到问题 - 他们是否期望一个函数返回一个返回一个对象的函数?或者一个对象具有作为键的键和作为值的函数?这个函数返回什么?即,文档不清楚mapDispatchToProps选项接受的所有不同变体。

1 个答案:

答案 0 :(得分:0)

如果您已经拥有lodash,则可以使用memoize函数将任何函数转换为memoized函数。这个memoized函数将计算给定参数的返回值,然后每次提供相同的参数时返回相同的返回值。

您可以像这样使用它:

import { memoize } from 'lodash'

const makeChangeDispatcher = memoize( (dispatch, path) => 
     value => dispatch({type: ActionTypes.Change, payload: {path, value}})
)

...

    (dispatch,ownProps) => { // <----------- mapDispatchToProps
        const path = [...getPath(ownProps),...toPath(ownProps[nameProp])];

        return {
            [dispatchProp]: makeChangeDispatcher(dispatch, path)
        };

    }

...

您可以在lodash documentation of memoize

上看到更多信息