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