Как объединить несколько редукторов внутри одного состояния?

Я пытаюсь создать приложение, которое имеет 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 ответов


Я не думаю, что вы можете сделать это, просто используя combineReducer. Поскольку combineReducer ожидает объект и каждое свойство этого объекта должно быть функция. Затем каждая функция в этом объекте создает отдельное свойство в дереве состояний redux, и значение этого свойства является значением, возвращаемым этой функцией (при отправке любого действия).

также вы не можете получить доступ к состоянию одного редуктора в другом редукторе, потому что redux передает только состояние этого конкретного редуктора функция. Это означает, что вы не можете получить/изменить состояние 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


учитывая, что вы хотите сделать несколько редукторов для свойств внутри каждого комментария, что-то вроде:

 comments: [ array of Comment]

тогда вы не должны объединять редукторы при создании своего магазина, что вы можете сделать, это создать только один редуктор для комментариев:

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