无法合并 Reducers()
Not able to combineReducers()
我在单独的文件夹中有两个减速器,用于单独的组件,结构类似于:
index.js
/componentOne
|_ componentOne.js
|_ componentOneActionCreator.js
|_ componentOneReducer.js
/componentTwo
|_ componentTwo.js
|_ componentTwoActionCreator.js
|_ componentTwoReducer.js
这些 Reducer 中的每一个都在应用程序中单独工作 - 当我 createStore
在 index.js
中(它们被 import
编辑) - 但如果我尝试使用 combineReducers()
,它们的功能都不起作用(但不会破坏 UI)。我认为这与状态有关 - 下面还有一些代码供参考:
index.js
const rootReducer = combineReducers({
componentOneReducer,
componentTwoReducer
});
let store = createStore(rootReducer, applyMiddleware(thunk))
componentOneReducer
export default(state = {}, payload) => {
let newState = JSON.parse(JSON.stringify(state));
switch (payload.type) {
case 'REQUEST_DATA':
newState.isLoading = true;
return newState;
case 'RECEIVE_DATA':
newState.isLoading = false;
newState.pageData = payload.payload;
newState.pageName = payload.payload.pageName;
return newState
default:
return state;
}
}
componentTwoReducer.js 与 componentOneReducer.js 非常相似但不完全相同。
componentOne.js
return (
<Layout>
<section>
<SectionHeader headerText={this.props.pageName}></SectionHeader>
....
function mapStateToProps(state, props) {
return {
pageName: state.pageName
}
}
function mapDispatchToProps(dispatch) {
return {
actions: {
getData: function() {
dispatch(getData());
}
}
}
}
export default connect(mapStateToProps, mapDispatchToProps) (componentOne);
知道我在这里遗漏了什么吗?
我怀疑你的问题是没有使用状态树键。通过在您的示例中使用 combineReducers,生成的状态树将由 reducer 命名。由于对象 shorthand { componentOneReducer }
变为 { componentOneReducer: componentOneReducer }
,而您可以明确地将其更改为例如{ reducerOne: componentOneReducer }
因此你的状态变成了这样:
{
componentOneReducer: {loading: false, pageData: 123},
componentTwoReducer: {loading: true, pageData: null}
}
将状态映射到道具时,您应该使用例如
const mapStateToProps = state => ({
loading: state.componentOneReducer.loading
pageData: state.componentOneReducer.pageData
})
并在组件中做this.props.loading
。
我还建议您放弃使用 JSON.parse(JSON.stringify(state))
并直接做一些不可变的事情。
export default(state = {}, payload) => {
switch (payload.type) {
case 'REQUEST_DATA': {
return {
...state,
isLoading: true;
};
}
case 'RECEIVE_DATA': {
return {
...state,
isLoading: false,
pageData: payload.payload,
pageName: payload.payload.pageName
}
}
default:
return state;
}
}
我在单独的文件夹中有两个减速器,用于单独的组件,结构类似于:
index.js
/componentOne
|_ componentOne.js
|_ componentOneActionCreator.js
|_ componentOneReducer.js
/componentTwo
|_ componentTwo.js
|_ componentTwoActionCreator.js
|_ componentTwoReducer.js
这些 Reducer 中的每一个都在应用程序中单独工作 - 当我 createStore
在 index.js
中(它们被 import
编辑) - 但如果我尝试使用 combineReducers()
,它们的功能都不起作用(但不会破坏 UI)。我认为这与状态有关 - 下面还有一些代码供参考:
index.js
const rootReducer = combineReducers({
componentOneReducer,
componentTwoReducer
});
let store = createStore(rootReducer, applyMiddleware(thunk))
componentOneReducer
export default(state = {}, payload) => {
let newState = JSON.parse(JSON.stringify(state));
switch (payload.type) {
case 'REQUEST_DATA':
newState.isLoading = true;
return newState;
case 'RECEIVE_DATA':
newState.isLoading = false;
newState.pageData = payload.payload;
newState.pageName = payload.payload.pageName;
return newState
default:
return state;
}
}
componentTwoReducer.js 与 componentOneReducer.js 非常相似但不完全相同。
componentOne.js
return (
<Layout>
<section>
<SectionHeader headerText={this.props.pageName}></SectionHeader>
....
function mapStateToProps(state, props) {
return {
pageName: state.pageName
}
}
function mapDispatchToProps(dispatch) {
return {
actions: {
getData: function() {
dispatch(getData());
}
}
}
}
export default connect(mapStateToProps, mapDispatchToProps) (componentOne);
知道我在这里遗漏了什么吗?
我怀疑你的问题是没有使用状态树键。通过在您的示例中使用 combineReducers,生成的状态树将由 reducer 命名。由于对象 shorthand { componentOneReducer }
变为 { componentOneReducer: componentOneReducer }
,而您可以明确地将其更改为例如{ reducerOne: componentOneReducer }
因此你的状态变成了这样:
{
componentOneReducer: {loading: false, pageData: 123},
componentTwoReducer: {loading: true, pageData: null}
}
将状态映射到道具时,您应该使用例如
const mapStateToProps = state => ({
loading: state.componentOneReducer.loading
pageData: state.componentOneReducer.pageData
})
并在组件中做this.props.loading
。
我还建议您放弃使用 JSON.parse(JSON.stringify(state))
并直接做一些不可变的事情。
export default(state = {}, payload) => {
switch (payload.type) {
case 'REQUEST_DATA': {
return {
...state,
isLoading: true;
};
}
case 'RECEIVE_DATA': {
return {
...state,
isLoading: false,
pageData: payload.payload,
pageName: payload.payload.pageName
}
}
default:
return state;
}
}