【问题标题】:Redux react root reducer slowing downRedux反应根减速器减慢
【发布时间】:2017-11-02 08:19:07
【问题描述】:

我正在使用 react 和 redux 构建一个应用程序。一项功能特性是根据状态过滤结果。 所以在每个类 Component 我都有这样的东西:

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”来保持状态!

【问题讨论】:

    标签: reactjs react-redux reducers


    【解决方案1】:

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

    我相信至少有 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 );
    });
    

    现在您可以通过 connectmapStateToProps 向您的组件提供filteredResults,而不必担心每次都过滤您的结果。

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

    优点

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

    缺点

    1. 由于过滤后的结果未存储在树中,因此您需要在要访问此数据的任何地方导入此选择器。
    2. 您将无法以直接方式访问它,例如state.xyz.filteredResults

    2。存储任何会更改过滤结果的内容时,将过滤结果存储在树中。

    您可以在存储结果和输入值的位置(以及何时)计算和存储过滤后的结果。 仅当您的原始结果存储在同一位置时,这才有可能。

    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. 您将能够手动访问您的过滤结果,因为它们存储在树中。

    缺点

    1. 您需要确保每个更改任何相关内容的操作都会更新过滤结果。
    2. 您将在存储中存储额外的数据(结果 + 过滤结果)。

    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. 您可以将过滤后的结果存储在树的不同部分,以存储结果或输入值。

    缺点

    1. 您需要一个额外的操作来存储过滤结果。
    2. 您正在分别调度 2 个可能导致额外渲染的操作。

    最终考虑

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

    我个人喜欢使用选择器 (1) 并重新计算数据,因为这允许我将逻辑与操作和化简器分开。

    【讨论】:

    • 非常感谢!我将尝试版本 (1) 并报告与“幼稚”解决方案相比是否有任何性能提升。另外,我必须承认性能测量并不是 100% 准确的。我用的是chrome,点击了触发过滤功能的按钮,记录在chrome中进行测量。但是,在这种情况下,很明显我的 RootReduced 表现更差。
    • 还添加了我在问题中使用的rootReducer。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多