如何在一个州内合并多个减速器?

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

标签: reactjs redux react-redux

我正在尝试构建一个具有two or more缩减器的应用程序"回答"我storeState内的一个对象。

示例:

storeState {
    app: {...},
    comments: [ ...two or more states inside one... ]
}

我已经使用了无法工作的combineReducers尝试了以下操作,我的comments状态变为空对象。

import { combineReducers } from 'redux';
import commentFacebookReducer from './twitch';
import commentYoutubeReducer from './reddit';
import appReducer from './app';

const rootReducer = combineReducers({
  comments: [commentFacebookReducer, commentYoutubeReducer],
  app: appReducer
});

export default rootReducer;

我已经尝试将我的评论缩减器组合起来,然后将它们合并到rootReducer

import { combineReducers } from 'redux';
import commentFacebookReducer from './twitch';
import commentYoutubeReducer from './reddit';
import appReducer from './app';

const commentReducers = combineReducers({
  commentFacebookReducer,
  commentYoutubeReducer
});

const rootReducer = combineReducers({
  comments: commentReducers,
  app: appReducer
});

export default rootReducer;

但它给了我一个像以下那样的storeState。但我需要一个注释数组的状态,我不能处理这些减少名称(如commentFacebookReducer或commentYoutubeReducer),因为我会有数千个这样的减速器。

storeState {
    app: {...},
    comments: {
        commentFacebookReducer: {...},
        commentYoutubeReducer: {...}
    }
}

2 个答案:

答案 0 :(得分:1)

我不认为你可以通过使用combineReducer来做到这一点。因为combineReducer需要一个对象,该对象的每个属性都应该是 一个功能。然后该对象中的每个函数在redux状态树中创建一个单独的属性,该属性的值是该函数返回的值(当调度任何操作时)。

此外,您无法在其他reducer中访问一个reducer的状态,因为redux仅将该特定的reducer状态传递给该函数。这意味着您无法在commentFacebookReducer内获取/更改commentYoutubeReducer的状态。

我现在能想到的唯一更好的解决方案是在使用它们时将它们组合在一起(很可能是在mapStateToProps中)。你按照这样的方式保留你的减速器:

const commentReducers = combineReducers({
  commentFacebookReducer,
  commentYoutubeReducer
});

const rootReducer = combineReducers({
  comments: commentReducers,
  app: appReducer
});

现在我们所有的评论都在一个对象中,即(state.comments)。现在在mapStateToProp中你可以做这样的事情,将它们组合在单个对象::

const mapStateToProps = state => {
    return {
        comments: Object.keys(state.comments).reduce((d, k) => {return d.concat(a[k])}, [] )
    };
};

现在在组件中,您可以使用this.props.comments

将它们作为单个数组进行访问

答案 1 :(得分:1)

考虑到你想要做的是每个评论中的属性的多个reducer,如:

 comments: [ array of Comment]

然后你不应该在创建商店时组合reducer,你可以做的只是为评论创建一个reducer:

comments: commentsReducer

然后commentsReducer将如下所示:

import {commentYouTubeReducer} from 'X'
import {commentFacebookReducer} from 'Y'

const commentsReducer = (state = [], action) => {

    switch (action.type){
       case 'ADD_COMMENT':
         return [..state, 
                {
                  YouTubeComment: commentYouTubeReducer(undefined, action),
                  FacebookComment: commentFacebookReducer(undefined, action)
                }]

    }     
} 

我知道这是一个非常简单的例子,但我猜你得到了我的想法。你所做的是在其中编写commentsReducer,但不是作为商店创建的一部分。对于更新的情况,您作为commentYoutubeReducer的状态传递的内容将是其先前的值,例如:

 ...
 case 'UPDATE_COMMENT':
 ...
 { youtubeComment: commentYoutubeReducer(comment.youtubeCommnet, action) ... }

基本上你的问题是你可以在这里找到的待办事项列表的概括:https://codepen.io/haakenlid/pen/qZOVjV