重构器重新选择选择器以获得更好的记忆

时间:2018-03-21 12:30:28

标签: javascript redux reselect

我正在使用Redux.js并重新选择库,我想知道如何重构以下选择器函数以便获得更好的memoization。情况是,即使更新citizen的详细信息,公民总数也始终保持不变。那么,只有在商店中添加新商品或删除商品时才有更好的方法来获取总计数吗?

export const getCitizensNumberByContinentSelector = () => {
    let getCountryIdsByContinent = getCountryIdsByContinentSelector();
    let getCityIdsByCountry = getCityIdsByCountrySelector();
    let getCitizenIdsByCity = getCitizenIdsByCitySelector();

    return createSelector(
        (store) => store,
        (store, continentId) => continentId,
        (store, continentId) => {
            let citizensCount = 0;

            let countryIdsByContinent = getCountryIdsByContinent(store, continentId);

            countryIdsByContinent.forEach(countryId => {
                let cityIdsByCountry = getCityIdsByCountry(store, countryId);

                cityIdsByCountry.forEach(cityId => {
                    let citizenIdsByCity = getCitizenIdsByCity(store, cityId);
                    citizensCount += citizenIdsByCity.length;
                });
            });

            return citizensCount;
        }
    );
};

function mapStateToProps(state) {
    let getCitizensNumberByContinent = getCitizensNumberByContinentSelector();

    return (store, ownProps) {
        return {
            citizensCount: getCitizensNumberByContinent(store, ownProps.continentId)
        };
    };
}

export default connect(mapStateToProps)(MyComponent);

1 个答案:

答案 0 :(得分:0)

您描述的问题可能通过以不同方式规范您的应用程序状态来解决

您的应用程序似乎当前正在存储公民信息,如下所示:

{
    cities: [
        {id: 1, name: 'london', citizens: ['tom', 'mat', 'jim']},
        {id: 2, name: 'madrid', citizens: ['mat', 'jim']},
        {id: 3, name: 'berlin', citizens: ['tom', 'jim']},
    ];
}

采用不变性方法后,当添加/删除新用户时, citiescities.citizens数组都会重新创建 >公民改名称

通过从城市列表中提取公民数据来规范化状态,将允许重新创建citiescities.citizens数组当公民实际被移除/添加/移动时。任何公民数据更新都只会影响根citizens阵列,从而帮助选择器不会丢失记忆。

{
    citizens: {
        byId: {
            1: {id: 1, name: 'tom'},
            2: {id: 2, name: 'mat'},
            3: {id: 3, name: 'jim'},
        },
        allIds: [1, 2, 3],
    }
    cities: {
        byId: {
            1: {id: 1, name: 'london', citizens: [1, 2, 3]},
            2: {id: 2, name: 'madrid', citizens: [2, 3]},
            3: {id: 3, name: 'berlin', citizens: [1, 3]},
        },
        allIds: [1, 2, 3],
    }
}

在这种情况下,检索公民身份证会非常简单,reselect就不再需要了:

function getCitizenIdsByCity(store, cityId) {
    return store.cities.byId[cityId].citizens;
}