了解 redux 中的 reducer 和 combineReducers
Understanding reducers and combineReducer in redux
所以我正在使用 redux,我写了一个 reducer 来管理待办事项;
import { combineReducers } from "redux";
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default combineReducers({
rootReducer,
});
如您所见,我创建了一个 reducer 和用户 combineReducer
,然后将其传递给存储在其他文件中,并且工作正常。
现在我对 combineReducer 的理解是,当我们单独编写它们时,它结合了分离的 reducer。因此,如果我将上面的减速器(因为我只有一个减速器)更改为以下;
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default rootReducer;
并将其传递给状态,但它给出了错误。当我尝试使用 useSelector
;
访问 todos
时,它给出了 undefined
const {todos} = useSelector(state => ({
todos: state.rootReducer.todos
}))
所以我认为我没有正确理解 combineReducers
。请解释导致上述错误的原因。
Combine reducer根据你传入的对象的key,为每个reducer控制的state添加命名空间。当你不使用combine reducer时,不会有命名空间。所以将 state.rootReducer 改为 state.
combineReducers
创建一个reducer 来分离组合reducer 的状态。在 documentation 他们展示了这个例子:
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
这将产生以下状态对象
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
}
}
因此当你写
combineReducers({
rootReducer,
});
状态对象将是
{
rootReducer: {
// rootReducer's state
}
}
在您的第二个示例中,您只是 return rootReducer
。因此没有单独的状态。 rootReducer
对根状态进行操作。因此,您必须调整选择。
const {todos} = useSelector(state => ({
todos: state.todos
}))
所以我正在使用 redux,我写了一个 reducer 来管理待办事项;
import { combineReducers } from "redux";
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default combineReducers({
rootReducer,
});
如您所见,我创建了一个 reducer 和用户 combineReducer
,然后将其传递给存储在其他文件中,并且工作正常。
现在我对 combineReducer 的理解是,当我们单独编写它们时,它结合了分离的 reducer。因此,如果我将上面的减速器(因为我只有一个减速器)更改为以下;
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default rootReducer;
并将其传递给状态,但它给出了错误。当我尝试使用 useSelector
;
todos
时,它给出了 undefined
const {todos} = useSelector(state => ({
todos: state.rootReducer.todos
}))
所以我认为我没有正确理解 combineReducers
。请解释导致上述错误的原因。
Combine reducer根据你传入的对象的key,为每个reducer控制的state添加命名空间。当你不使用combine reducer时,不会有命名空间。所以将 state.rootReducer 改为 state.
combineReducers
创建一个reducer 来分离组合reducer 的状态。在 documentation 他们展示了这个例子:
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
这将产生以下状态对象
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
}
}
因此当你写
combineReducers({
rootReducer,
});
状态对象将是
{
rootReducer: {
// rootReducer's state
}
}
在您的第二个示例中,您只是 return rootReducer
。因此没有单独的状态。 rootReducer
对根状态进行操作。因此,您必须调整选择。
const {todos} = useSelector(state => ({
todos: state.todos
}))