Redux反应减速器减速

时间:2017-11-02 08:19:08

标签: reactjs react-redux reducers

我正在使用react和redux构建应用程序。一个功能是根据状态过滤结果。 所以在每个类组件中我都有类似的东西:

filteredResults = this.filterResults(this.props.value1, this.props.value2,...)

现在我认为只要将filteredResults添加到redux状态并引入RootReducer就应该有性能提升。实际上,这减缓了应用程序的速度。任何想法为什么会这样?对我来说,这有点违反直觉,因为现在多次计算过滤掉的结果。

PS:这就是我的RootReducer的样子:

import {_getFilteredResults} from "../components/utils";


const createFilterRootReducer = reducer => (state, action) => {
  let reduced_state =  reducer(state, action);
  let filteredResults = _getFilteredResults(reduced_state.value1, reduced_state.value2, reduced_state.value3, reduced_state.results);
  return {...reduced_state, filteredResults:filteredResults}
};


export default createFilterRootReducer;

这适用于myRootReducer

const rootReducer = combineReducers({
    searching: ReducerSearching,
    roomOption: ReducerZimmer,
    maxPrice: ReducerMaxPrice,
    minPrice: ReducerMinPrice,
    internalMaxPrice: ReducerInternalMaxPrice,
    Address: ReducerAddress,
    Results: ReducerResults,
    activePage: ReducerActivePage,
    favoriteResults:ReducerLikedItems,
    resultSort: ReducerSort,
    acceptedCookie: ReducerCookies,
    headerHeight: ReducerHeaderHeight,
    mapView: ReducerMapView,
    rehydrate: ReducerRehydrate

});
export default createFilterRootReducer(rootReducer);

还有一件事:我还在使用'redux-persist'来坚持这个州!

1 个答案:

答案 0 :(得分:2)

好吧,如果您能提供一些额外的信息和您正在使用的代码,将会很有帮助。

我相信至少有3种方法可以做你想要达到的目标。

1。使用createSelector重新选择

在我看来,最简单的方法是让选择器根据整个结果的实际状态和过滤值来计算过滤结果。

import { createSelector } from 'reselect';
const getResults = state => state.results; // e.g. array of strings
const getFilter = state => state.filter; // e.g. an input value 

export const filteredResults = createSelector( getResults, getFilter, ( results, filter ) => {
    return results.filter( item => item.indexOf( filter ) != -1 );
});

现在,您可以通过 connect mapStateToProps 向您的组件提供filteredResults,而无需每次都过滤结果。

请注意,createSelector足够聪明,可以对其参数执行相等检查,以便仅在任何参数更改时重新计算函数。

赞成

  1. 您不需要将过滤后的结果存储在状态树
  2. 缺点

    1. 由于过滤后的结果未存储在树中,因此您需要在要访问此数据的任何位置导入此选择器。
    2. 您无法直接访问它,例如state.xyz.filteredResults
    3. 2。存储可能会改变它们的任何内容时,将过滤后的结果存储在树中。

      您可以在同一树分支中计算并存储filteredResults,其中(以及何时)存储结果和输入值。 只有当您的原始结果存储在同一位置时,才可以这样做。

      const initialState = {
          results: [],
          filteredResults: [],
          filter: ''
      }
      
      const filterResults = ( results, filter ) => results.filter( item => item.indexOf( filter ) )
      
      const myReducer = handleActions({
          [SET_RESULTS]: (state, action) => ({
              ...state,
              results: action.payload,
              filteredResults: filterResults( action.payload, state.filter )
          }),
          [SET_FILTER]:  (state, action) => ({
              ...state,
              filter: action.payload,
              filteredResults: filterResults( state.results, action.payload )
          })
      }, initialState)
      

      赞成

      1. 您可以手动访问您的filteredResults,因为它们存储在树中。
      2. 缺点

        1. 您需要确保每个操作都会更改已经过滤的结果会更新它们。
        2. 您将在商店中存储额外数据(结果+过滤结果)。
        3. 3。使用Redux-Thunk并存储过滤结果

          这是一种不同的方法。 基本上,当您输入时,您可以将过滤后的结果存储在树的不同部分,但为了做到这一点,您将需要Redux Thunk中间件

          export const onChangeInputValue = ( value ) => {
              return (dispatch, getState) => {
          
                  const results = getResults( getState() )
                  const filteredResults = results.filter( item => item.indexOf( value ) )
          
                  dispatch( setInputValue( value ) )
                  dispatch( setFilteredResults( filteredResults ) )
              }   
          }
          

          赞成

          1. 您可以将过滤后的结果存储在树的不同部分,以存储结果或输入值。
          2. 缺点

            1. 您需要一个额外的操作来存储过滤后的结果。
            2. 您将分别调度2个可能导致额外渲染的操作。
            3. 最后的考虑

              根据您的需要,您可以选择最合适和最可行的方式。

              我个人喜欢使用选择器(1)并重新计算数据,因为这样我就可以将逻辑与动作和缩减器分开。