使用 combineReducers() 给出的运行时结果与单个 reducer 不同

Posted

技术标签:

【中文标题】使用 combineReducers() 给出的运行时结果与单个 reducer 不同【英文标题】:using combineReducers() gives different runtime result than single reducer 【发布时间】:2018-11-11 17:08:21 【问题描述】:

我正在尝试从具有初始状态的根减速器初始化基本存储。

我的根减速器

import Entity from "../api/Entity";
import  UPDATE_GROUPING  from "../constants/action-types";
import IAction from "../interfaces/IAction";
import IStoreState from "../interfaces/IStoreState";

const initialState:IStoreState = 
  callsInProgress: false,
  groupingOptions: ["Strategy", "User", "Date"],
  groupingType: "Strategy",
  numberOfCalls: 2,
  items: [new Entity()],
;


const rootReducer = (state = initialState, action: IAction<object>) =>   
  switch (action.type) 
    case UPDATE_GROUPING:
      return  ...state, groupingType: action.payload;
    default:
      return state;
    
;

export default rootReducer;

当我使用 rootreducer 创建商店时,如下所示

import  createStore  from 'redux';
import rootreducer  from '../reducers/rootreducer';

const store = createStore(rootreducer);
export default store;

它有效。 React 组件被初始化为 groupingType、groupingOptions 等的正确状态。

但是,如果我尝试使用 combineReducers() 方法 - 即使只有这个单一的根减速器(应该是相同的),那么当我的组件加载时,它们不会传递任何初始状态。

import  createStore  from 'redux';
import reducers  from '../reducers';

const store = createStore(reducers);
export default store;

reducers 文件夹中的我的 index.ts 返回了 combineReducers() 调用(不起作用的那个)

import combineReducers from 'redux';
import rootreducer from './rootreducer';

// main reducers
export default combineReducers(
  rootreducer
);

最后是我的组件,它连接到 redux 并且应该从 redux 存储中导入状态

import updateGroupingType from "./actions/uiactions";
import './App.css';
import * as React from 'react';
import  connect  from 'react-redux';
import IStoreState from './interfaces/IStoreState';

interface IGroupingProps 
    groupingOptions? : string[],
    groupingType? : string,
    updateGroupingAction? : any
  

class GroupingSelector extends React.Component<IGroupingProps, > 

    constructor(props: IGroupingProps) 
        super(props);

        this.onGroupingChange = this.onGroupingChange.bind(this);
      

      public render() 
            if (this.props.groupingOptions == null)
            
                return null;
            

                return (
            <div className="Grouping-selector">
                <div className="Horizontal-panel-right Grouping-search-combo">
                    <select onChange=this.onGroupingChange>
                        this.props.groupingOptions.map((name, index)=> 
                            <option key=index>name</option>
                        )
                    </select>
                </div>
                <div className="Content Horizontal-panel-right">
                    Group by
                </div>            
            </div>);
        

    private onGroupingChange(e: any) 
          const  value  = e.target;
          this.props.updateGroupingAction(value);
          


const mapStateToProps:any = (state: IStoreState) => 
    return 
        groupingOptions: state.groupingOptions,
        groupingType: state.groupingType,
    ;
      

const mapDispatchToProps = (dispatch:any) => 
    return 
        updateGroupingAction: (groupingType:string) => dispatch(updateGroupingType(groupingType))
    ;
;

export default connect(mapStateToProps, mapDispatchToProps)(GroupingSelector);

为什么我使用 combineReducer 的方式与使用单个 rootreducer 时的方式不同?

【问题讨论】:

【参考方案1】:

From the doc

combineReducers 辅助函数将值是不同归约函数的对象转换为可以传递给 createStore 的单个归约函数。

生成的 reducer 调用每个子 reducer,并将它们的结果收集到单个状态对象中。 combineReducers() 生成的状态命名空间将每个 reducer 的状态在其键下传递给 combineReducers()

当你在 combineReducers 中使用 rootReducer 作为键时,它会创建一个形状为的状态

"rootReducer": YOUR_PREVIOUS_STATE

只有在每个键都有不同的 reducer 时,才应该使用 combineReducers

【讨论】:

啊,基本错误。这是否意味着每个 reducer 应该有不同的状态对象定义,所以当我将初始状态传递给每个子 reducer 时,它们每个都有自己的状态定义,而不是共享一个全局扁平状态映射? 是的,如果你有foo: true, bar: false,那么在combineReducers(foo: fooReducer, bar: barReducer) fooReducer 将有true【参考方案2】:

你的根 reducer 应该是键值对,例如,

export default combineReducers(
  home:homeReducer
);

因此,在您的组件中,mapStateToProps() 您将能够访问这些值,

const mapStateToProps = (state: any) => 
  return 
    users: state.home
  ;
;

【讨论】:

以上是关于使用 combineReducers() 给出的运行时结果与单个 reducer 不同的主要内容,如果未能解决你的问题,请参考以下文章

Redux - 理解 combineReducers

combineReducers 无法正常工作。任何人都可以看到问题吗?

combineReducers 破坏 Redux 状态并破坏多个 ImmutableJs 减速器

Redux 中 combineReducers实现原理

combineReducers

如何用 jest 测试 combineReducers