如何分离相互依赖的redux减速器?

时间:2017-10-30 10:04:04

标签: javascript reactjs redux reducers

我有一个小应用程序,其中向用户显示一个小列表,她可以动态过滤。

所以我认为我的状态看起来像是:

{ data: [], filters: {}, filteredData: [] }

..这可能是一个坏主意。

到目前为止,我还只有一个减速器,可以响应动作:

  • UPDATE_FILTERS
  • 初始 DATA_RECEIVED (页面加载时只有一次)。

我的减速机看起来像这样:

import {UPDATE_FILTERS, DATA_RECEIVED} from '../actions/actions'

function getFilteredDataRows(filters, data){

    const distanceMin = parseInt(filters.distanceMin) || 0;
    const distanceMax = parseInt(filters.distanceMax) || 9999999999;
    const location = filters.location || '';
    return (
        data
        .filter((swim) => swim.location.toLowerCase().includes(location.toLowerCase()))
        .filter((swim) => swim.distance > distanceMin)
        .filter((swim) => swim.distance < distanceMax)
    );
}

const filterReducer = (state = [], action) => {
    switch(action.type){
        case UPDATE_FILTERS:
            const newFilters = Object.assign({}, state.filters, action.filters);
            return { filters : newFilters, data: state.data, filteredData: getFilteredDataRows(newFilters, state.data)};

        case DATA_RECEIVED:
            return {filters : state.filters, data: action.data, filteredData: getFilteredDataRows(state.filters, action.data)};
        default:
            return state
    }
}


export default filterReducer;

所有这一切都有效。但对我来说,它也很臭。 我已经关注了redux教程(Dan。与Todo&#39;)之一

我希望能够将减速器分成两部分:

  • FilterReducer(过滤器更新)
  • DataReducer(filteredData updates)

但是第二个依赖于第一个,我不知道如何以干净的方式做到这一点。

你有什么想法吗?

提前致谢

3 个答案:

答案 0 :(得分:2)

可以在多个Reducer中侦听相同的操作。

UPDATE_FILTERSfilterReducer中收听filteredDataReducer操作。

在filterReducer中,修改商店的过滤器部分。

在filteredData reducer中,修改商店的数据部分。

<强> filterReducer.js:

const filterReducer = (state = [], action) => {
   switch(action.type){
        case UPDATE_FILTERS:
   return Object.assign({}, state, filters: action.filters);
        default:
            return state
    }
}

<强> filteredData.js:

const filteredDataReducer = (state = [], action) => {
switch(action.type){
        case UPDATE_FILTERS:
            return Object.assign({}, state, filteredData: getFilteredData(action.filters, state.data));
        default:
            return state
    }
}

答案 1 :(得分:1)

问题在于您的第一行粘贴代码。

您保持状态数据和当前过滤器。过滤的数据是派生状态(意味着它可以从其他状态块计算),并且应该在您的React组件中“计算”。如果datafilter都没有更改,connect将不会重新呈现您的组件。

getFilteredData移动到接收整个状态的选择器并返回UI所需的特定数据,而不是存储它。

由于您没有使用该数据显示任何React代码,因此我无法帮助您。对于复杂的选择器,您最终会查看reselect,这在Redux文档中有很好的解释:

http://redux.js.org/docs/recipes/ComputingDerivedData.html

答案 2 :(得分:0)

如果这些是真正的需求而不是一些简化,我将不会使用Redux,只是在React中管理状态。

问题:

状态不应该是filteredData,只有数据和过滤器。

getFilteredDataRows方法应该从显示数据的反应组件的render函数调用,或者从mapStateToProps

调用

请参阅the Redux docs了解实施容器组件,其getVisibleTodos就像您的getFilteredDataRows