在 redux 初始状态和 reducer 中使用嵌套对象
Using nested objects in redux initial state and reducers
我的仪表板有一个由 react-router 分隔的部分。
部分是:
类别
考试
报告
让我们看看考试部分。我们将此状态作为初始状态。
{
ID: null,
RandomizeQuestions: false,
RandomizeAnswers: false,
Pages: [
{
ID: 1,
Title: 'Page one',
Blocks: [
{
ID: 1,
Title: 'Block One',
Questions: [
{
ID: 1,
Title: "Quesiton title is here",
Answers: [
{
ID: 1,
Title: "Answer 1"
},
{
ID: 2,
Title: "Answer 2"
}
]
}
]
}
]
}
]
}
我知道我用redux的时候应该把state扁平化归一化。但那是我的确切问题。如果我尝试使我的状态正常化,它应该是这样的:
{
Exam: {
ID: null,
RandomizeQuestions: false,
RandomizeAnswers: false
},
ExamPages: [
{
ExamId: 1,
ID: 1,
Title: 'Page One'
}
],
ExamBlocks: [
{
ID: 1,
Title: 'The New Block',
Questions: []
}
],
ExamQuestions: [],
ExamAnswers: []
}
让我们假设它没问题,我不会有问题。但是其他部分什么时候发生?
类别 有自己的状态,也很大,也有报告。 (还有其他部分我没有提到)
然后我的 combineReducer 看起来像这样:
import {combineReducers} from 'redux'
import Exam from './redc.exams.jsx'
import ExamBlocks from './redc.blocks.jsx'
const rootReducer = combineReducers({
Exam,
ExamBlocks
})
export default rootReducer
当然,我应该为该对象中的每个数组设置一个 reducer。
所以我的主要问题是我怎样才能至少有这个结构:
const initialState = {
Exams: {
Blocks: [],
Questions: [],
Answers: []
},
Categories: {
Menus: [],
Users: []
},
Report: {
MainReports: [],
SideReports: []
}
}
请记住,我想为它们中的每一个都设置单独的减速器。
Blocks 的 reducer,Questions 的 reducer 等等...
更新 #1
我试过 @Tom Fenech 在答案中说的但不能在最终的 combineReducers 之前组合 reducers。
现在我的根减速器是这样的:
import {combineReducers} from 'redux'
//Exams
import Exams from './ExamsReducers/redc.exams.jsx'
import Blocks from './ExamsReducers/redc.blocks.jsx'
//Categories
import Categories from './CategoriesReducers/redc.categories.jsx'
const rootReducer = combineReducers({
Exams,
Categories,
Blocks,
})
export default rootReducer
我试过他说的,这是我修改后的代码:
import {combineReducers} from 'redux'
//Exams
import Exams from './ExamsReducers/redc.exams.jsx'
import Blocks from './ExamsReducers/redc.blocks.jsx'
//Categories
import Categories from './CategoriesReducers/redc.categories.jsx'
const examRedc = combineReducers(Exams,Blocks )
const catsRedc = combineReducers(Categories)
const rootReducer = combineReducers(examRedc, catsRedc)
export default rootReducer
我收到这个错误:
Store does not have a valid reducer. Make sure the argument passed to combineReducers is an object whose values are reducers.
当我像这样在其中一个组件中记录状态时
var mapDispatchToProps = function (dispatch) {
return {
AddBlock: function () {
dispatch(addBlock());
}
}
};
const mapStateToProps = function (state) {
console.log(state); //////HERE
return {Blocks: state.Blocks};
}
export default connect(mapStateToProps, mapDispatchToProps)(Blocks)
我终于得到了这个不是我想要的状态。
你可以有像
这样的嵌套reducer结构
// block_reducer.js
export const reducer = (state = [], action) => {
switch (action.type) {
case BLOCK_ACTION:
return [{a:1}, {b:2}]
}
return state
}
// exam_reducer.js
import {combineReducers} from 'redux'
import {reducer as BlockReducer} from './block_reducer'
export const reducer = combineReducers({
Blocks: BlockReducer,
Sections: .....,
Answers: .......
})
// root_reducer.js
import {combineReducers} from 'redux'
import {reducer as examReducers} from './exam_reducers'
export const reducer = combineReducers({
Exams: examReducers,
Categories: .....,
Report: ......
})
我认为 Exams
中不需要 Blocks
、Questions
和 Answers
。我会在顶层提出这样的建议:
{
Exams: {
[ID]: {
ID: string,
RandomizeQuestions: boolean,
RandomizeAnswers: boolean,
Blocks: string[] // array of block IDs
}
}
Blocks: {
[ID]: {
ID: string,
Title: string,
Questions: string[] // array of question IDs
}
},
Questions: // etc.
}
现在,我们不存储嵌套对象,而是存储它们的 ID 以跟踪所有权。
此状态将创建为:
state = combineReducers({
examsReducer,
blocksReducer,
// ...more reducers
})
如果你想把整个状态分成几个部分,你可以使用这样的东西:
const examStuff = combineReducers({
examsReducer,
blocksReducer,
// ...
});
const categoryStuff = combineReducers({
categoriesReducer,
menusReducer,
// ...
});
const state = combineReducers({
examStuff,
categoryStuff
});
那么状态将是:
{
examStuff: {} // the object defined at the top of question,
categoryStuff: {},
otherStuff: {}
}
我的仪表板有一个由 react-router 分隔的部分。
部分是:
类别
考试
报告
让我们看看考试部分。我们将此状态作为初始状态。
{
ID: null,
RandomizeQuestions: false,
RandomizeAnswers: false,
Pages: [
{
ID: 1,
Title: 'Page one',
Blocks: [
{
ID: 1,
Title: 'Block One',
Questions: [
{
ID: 1,
Title: "Quesiton title is here",
Answers: [
{
ID: 1,
Title: "Answer 1"
},
{
ID: 2,
Title: "Answer 2"
}
]
}
]
}
]
}
]
}
我知道我用redux的时候应该把state扁平化归一化。但那是我的确切问题。如果我尝试使我的状态正常化,它应该是这样的:
{
Exam: {
ID: null,
RandomizeQuestions: false,
RandomizeAnswers: false
},
ExamPages: [
{
ExamId: 1,
ID: 1,
Title: 'Page One'
}
],
ExamBlocks: [
{
ID: 1,
Title: 'The New Block',
Questions: []
}
],
ExamQuestions: [],
ExamAnswers: []
}
让我们假设它没问题,我不会有问题。但是其他部分什么时候发生?
类别 有自己的状态,也很大,也有报告。 (还有其他部分我没有提到)
然后我的 combineReducer 看起来像这样:
import {combineReducers} from 'redux'
import Exam from './redc.exams.jsx'
import ExamBlocks from './redc.blocks.jsx'
const rootReducer = combineReducers({
Exam,
ExamBlocks
})
export default rootReducer
当然,我应该为该对象中的每个数组设置一个 reducer。
所以我的主要问题是我怎样才能至少有这个结构:
const initialState = {
Exams: {
Blocks: [],
Questions: [],
Answers: []
},
Categories: {
Menus: [],
Users: []
},
Report: {
MainReports: [],
SideReports: []
}
}
请记住,我想为它们中的每一个都设置单独的减速器。 Blocks 的 reducer,Questions 的 reducer 等等...
更新 #1
我试过 @Tom Fenech 在答案中说的但不能在最终的 combineReducers 之前组合 reducers。 现在我的根减速器是这样的:
import {combineReducers} from 'redux'
//Exams
import Exams from './ExamsReducers/redc.exams.jsx'
import Blocks from './ExamsReducers/redc.blocks.jsx'
//Categories
import Categories from './CategoriesReducers/redc.categories.jsx'
const rootReducer = combineReducers({
Exams,
Categories,
Blocks,
})
export default rootReducer
我试过他说的,这是我修改后的代码:
import {combineReducers} from 'redux'
//Exams
import Exams from './ExamsReducers/redc.exams.jsx'
import Blocks from './ExamsReducers/redc.blocks.jsx'
//Categories
import Categories from './CategoriesReducers/redc.categories.jsx'
const examRedc = combineReducers(Exams,Blocks )
const catsRedc = combineReducers(Categories)
const rootReducer = combineReducers(examRedc, catsRedc)
export default rootReducer
我收到这个错误:
Store does not have a valid reducer. Make sure the argument passed to combineReducers is an object whose values are reducers.
当我像这样在其中一个组件中记录状态时
var mapDispatchToProps = function (dispatch) {
return {
AddBlock: function () {
dispatch(addBlock());
}
}
};
const mapStateToProps = function (state) {
console.log(state); //////HERE
return {Blocks: state.Blocks};
}
export default connect(mapStateToProps, mapDispatchToProps)(Blocks)
我终于得到了这个不是我想要的状态。
你可以有像
这样的嵌套reducer结构// block_reducer.js
export const reducer = (state = [], action) => {
switch (action.type) {
case BLOCK_ACTION:
return [{a:1}, {b:2}]
}
return state
}
// exam_reducer.js
import {combineReducers} from 'redux'
import {reducer as BlockReducer} from './block_reducer'
export const reducer = combineReducers({
Blocks: BlockReducer,
Sections: .....,
Answers: .......
})
// root_reducer.js
import {combineReducers} from 'redux'
import {reducer as examReducers} from './exam_reducers'
export const reducer = combineReducers({
Exams: examReducers,
Categories: .....,
Report: ......
})
我认为 Exams
中不需要 Blocks
、Questions
和 Answers
。我会在顶层提出这样的建议:
{
Exams: {
[ID]: {
ID: string,
RandomizeQuestions: boolean,
RandomizeAnswers: boolean,
Blocks: string[] // array of block IDs
}
}
Blocks: {
[ID]: {
ID: string,
Title: string,
Questions: string[] // array of question IDs
}
},
Questions: // etc.
}
现在,我们不存储嵌套对象,而是存储它们的 ID 以跟踪所有权。
此状态将创建为:
state = combineReducers({
examsReducer,
blocksReducer,
// ...more reducers
})
如果你想把整个状态分成几个部分,你可以使用这样的东西:
const examStuff = combineReducers({
examsReducer,
blocksReducer,
// ...
});
const categoryStuff = combineReducers({
categoriesReducer,
menusReducer,
// ...
});
const state = combineReducers({
examStuff,
categoryStuff
});
那么状态将是:
{
examStuff: {} // the object defined at the top of question,
categoryStuff: {},
otherStuff: {}
}