Redux:使用 thunk 中间件和 combineReducers 为 getState 引入了额外的键
Redux: using thunk middleware and combineReducers introduces extra key to getState
问题:在引入 Redux.combineReducers
之前使用 thunk
中间件时,getState
正确传递给 thunk returns 具有正确键的对象。重构为使用 Redux.combineReducers
后,getState
现在传递给 thunk returns 一个具有嵌套键的对象。请参阅下面的代码(希望)说明我的观点。这可能会导致潜在的维护噩梦,即必须不断为任何访问状态的 thunk
方法获取正确的密钥。
问题:有没有一种简单的方法可以在 thunk
中设置正确的上下文键?当我组合 reducer 并且必须插入键才能访问正确的状态时,代码感觉很脆弱。我错过了一些简单的东西吗?
代码前:
const Redux = require('redux'),
Thunk = require('redux-thunk');
// this is an action generator that returns a function and is handled by thunk
const doSomethingWithFoo = function() {
return function(dispatch, getState) {
// here we're trying to get state.fooValue
const fooValue = getState().fooValue;
dispatch({ type: "DO_SOMETHING", fooValue });
}
};
// this is a simple action generator that returns a plain action object
const doSimpleAction = function(value) {
// we simply pass the value to the action.
// we don't have to worry about the state's context at all.
// combineReducers() handles setting the context for us.
return { type: "SIMPLE_ACTION", value };
}
const fooReducer(state, action) {
// this code doesn't really matter
...
}
const applyMiddleware = Redux.applyMiddleware(Thunk)(Redux.createStore);
const fooStore = applyMiddleware(fooReducer);
代码后(引入更全球化的应用商店):
// need to rewrite my thunk now because getState returns different state shape
const doSomethingWithFoo = function() {
return function(dispatch, getState) {
// here we're trying to get state.fooValue, but the shape is different
const fooValue = getState().foo.fooValue;
dispatch({ type: "DO_SOMETHING", fooValue });
}
};
const appReducers = Redux.combineReducers({
foo: fooReducer,
bar: barReducer,
});
const appStore = applyMiddleware(appReducers);
再考虑一下后,我认为答案是重构 doSomethingWithFoo
动作生成器,使其接受 fooValue
作为参数。这样我就不用担心状态对象的形状改变了。
const doSomethingWithFoo(fooValue) {
return function(dispatch, getState) {
// now we don't have to worry about the shape of getState()'s result
dispatch({ type: "DO_SOMETHING", fooValue });
}
}
你是 over-thinking 东西。根据定义,store.getState()
returns 整个状态,combineReducers()
将多个 sub-reducers 拉到一起成为一个更大的对象。两者都按预期工作。您正在编写自己的应用程序,因此您要对实际组织状态形状和处理它的方式负责。如果你觉得事情太过"brittle"这样,那么你可以找到一个好的方式来组织事情,但这不是 Redux 的问题。
此外,在动作创建器中使用 getState()
来确定要做什么是一种完全有效的方法。事实上,Redux 文档的 Reducing Boilerplate 部分甚至将其作为演示:
export function addTodo(text) {
// This form is allowed by Redux Thunk middleware
// described below in “Async Action Creators” section.
return function (dispatch, getState) {
if (getState().todos.length === 3) {
// Exit early
return
}
dispatch(addTodoWithoutCheck(text))
}
}
问题:在引入 Redux.combineReducers
之前使用 thunk
中间件时,getState
正确传递给 thunk returns 具有正确键的对象。重构为使用 Redux.combineReducers
后,getState
现在传递给 thunk returns 一个具有嵌套键的对象。请参阅下面的代码(希望)说明我的观点。这可能会导致潜在的维护噩梦,即必须不断为任何访问状态的 thunk
方法获取正确的密钥。
问题:有没有一种简单的方法可以在 thunk
中设置正确的上下文键?当我组合 reducer 并且必须插入键才能访问正确的状态时,代码感觉很脆弱。我错过了一些简单的东西吗?
代码前:
const Redux = require('redux'),
Thunk = require('redux-thunk');
// this is an action generator that returns a function and is handled by thunk
const doSomethingWithFoo = function() {
return function(dispatch, getState) {
// here we're trying to get state.fooValue
const fooValue = getState().fooValue;
dispatch({ type: "DO_SOMETHING", fooValue });
}
};
// this is a simple action generator that returns a plain action object
const doSimpleAction = function(value) {
// we simply pass the value to the action.
// we don't have to worry about the state's context at all.
// combineReducers() handles setting the context for us.
return { type: "SIMPLE_ACTION", value };
}
const fooReducer(state, action) {
// this code doesn't really matter
...
}
const applyMiddleware = Redux.applyMiddleware(Thunk)(Redux.createStore);
const fooStore = applyMiddleware(fooReducer);
代码后(引入更全球化的应用商店):
// need to rewrite my thunk now because getState returns different state shape
const doSomethingWithFoo = function() {
return function(dispatch, getState) {
// here we're trying to get state.fooValue, but the shape is different
const fooValue = getState().foo.fooValue;
dispatch({ type: "DO_SOMETHING", fooValue });
}
};
const appReducers = Redux.combineReducers({
foo: fooReducer,
bar: barReducer,
});
const appStore = applyMiddleware(appReducers);
再考虑一下后,我认为答案是重构 doSomethingWithFoo
动作生成器,使其接受 fooValue
作为参数。这样我就不用担心状态对象的形状改变了。
const doSomethingWithFoo(fooValue) {
return function(dispatch, getState) {
// now we don't have to worry about the shape of getState()'s result
dispatch({ type: "DO_SOMETHING", fooValue });
}
}
你是 over-thinking 东西。根据定义,store.getState()
returns 整个状态,combineReducers()
将多个 sub-reducers 拉到一起成为一个更大的对象。两者都按预期工作。您正在编写自己的应用程序,因此您要对实际组织状态形状和处理它的方式负责。如果你觉得事情太过"brittle"这样,那么你可以找到一个好的方式来组织事情,但这不是 Redux 的问题。
此外,在动作创建器中使用 getState()
来确定要做什么是一种完全有效的方法。事实上,Redux 文档的 Reducing Boilerplate 部分甚至将其作为演示:
export function addTodo(text) {
// This form is allowed by Redux Thunk middleware
// described below in “Async Action Creators” section.
return function (dispatch, getState) {
if (getState().todos.length === 3) {
// Exit early
return
}
dispatch(addTodoWithoutCheck(text))
}
}