Redux - 有什么方法可以访问 reducer 中的存储树?
Redux - Is there any way to access store tree in reducer?
就我而言,我有这样一家商店:
{
aa: {...},
bb: cc // the result of computing with aa
}
我需要同时更新aa
和bb
,但是bb
需要获取aa
的最新计算。
这是一些代码(React.js):
onClick(e) {
const { dispatch, aa, bb } = this.props;
dispatch(updateAa());
dispatch(updateBb(aa)); // can not get the latest computation of aa, it is the last computation..
}
那么,这是否意味着我需要在 bb
的减速器中获得 aa
?
我该怎么做?
希望得到帮助!谢谢!
有多种可能性,但鉴于代码含糊不清,很难说哪种可能性最好。
- 理想情况下,指南中描述的 your store should be normalized, meaning that each piece of data is only available in one place. Then you would calculate derived data after reading the store, such as when you use the selector pattern 将商店的状态映射到您可能认为的物化视图,该视图将作为
props
发送到您的组件。在此工作流程中,aa
和 bb
将分别由选择器函数生成,而不是存储在该存储本身中。
- 您可以将更新
aa
和 bb
的减速器留在 combineReducers
之外,以便它看到整个状态,而不是范围缩小到 [=11= 的状态] 和 bb
.
- 您可以将您的计算代码提取到可以由
updateAa
和 updateBb
调用的帮助程序中,并在每个操作中传递足够的信息以进行计算。
- 您可以在调度之前计算更新,以便操作包含正确的值。
问问自己是否正确构建了减速器。如果 a 和 b 不是彼此独立的,为什么它们是单独的减速器?我会尝试将它们合并成一个减速器。
不要使用 combineReducers.
例子
替换此代码
export const a = combineReducers({
app,
posts,
intl,
products,
pos,
cats,
});
和
export default (state = {}, action) => {
return {
app: app(state.app, action, state),
posts: posts(state.posts, action, state),
intl: intl(state.intl, action, state),
products: products(state.products, action, state),
pos: pos(state.pos, action, state),
cats: cats(state.cats, action, state),
};
};
reducer 会像
const reducer = (state = initialState, action, root) => {....}
正如 David L. Walsh 所说,您可能应该以更合乎逻辑的方式构建 reducer。
BUT 如果你仍然认为你需要它,你可以使用一个 thunk 中间件。
(https://github.com/gaearon/redux-thunk)
Redux Thunk 中间件允许您编写 return 函数而不是动作的动作创建器。
Redux Thunk 为您提供了一种读取 Redux 存储当前状态的方法。除了调度之外,它还会将 getState 作为第二个参数传递给您 return 来自您的 thunk 动作创建者的函数。
export function action() {
return function(dispatch, getState){
const state = getState()
dispatch({
type: "ACTION_WITH_SOME_PART_OF_STATE,
some_part_of_state: state.some_part
})
}
}
如果某个reducer 需要来自另一个reducer 的一些数据,一个简单的解决方案是将它们合并到一个reducer 中。
就我而言,我需要来自另一个减速器的一些数据,而且很难管理它们,所以我最终将它们合并了。
根据 Sheikh Abdul Wahid 的回答,我不得不进行以下修改以使其适用于 history
和 connected-react-router
:
注意connectRouter(history)
后面的()
import { connectRouter } from 'connected-react-router'
const createRootReducer = (history) => {
return (state = {}, action) => {
return {
...reducers,
router: connectRouter(history)(),
...rest of reducers
}
}
}
如果这是您的常见用例,您可以尝试编写自己的函数来根据需要组合减速器,如 official Redux documentation:
所推荐
在 slice reducer 之间共享数据
类似地,如果 sliceReducerA 恰好需要 sliceReducerB 的状态切片中的一些数据来处理特定操作,或者 sliceReducerB 恰好需要整个状态作为参数,则 combineReducers 不会自行处理。这可以通过编写一个自定义函数来解决,该函数知道在这些特定情况下将所需数据作为附加参数传递,例如:
function combinedReducer(state, action) {
switch (action.type) {
case 'A_TYPICAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
b: sliceReducerB(state.b, action)
}
}
case 'SOME_SPECIAL_ACTION': {
return {
// specifically pass state.b as an additional argument
a: sliceReducerA(state.a, action, state.b),
b: sliceReducerB(state.b, action)
}
}
case 'ANOTHER_SPECIAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
// specifically pass the entire state as an additional argument
b: sliceReducerB(state.b, action, state)
}
}
default:
return state
}
}
我强烈建议您阅读 this documentation page,其中还有其他关于在 reducer 之间共享数据的建议,甚至使用 combineReducers
进行简单的操作,并在特殊情况下使用其他自定义的 reducer。
希望这些选项对您有所帮助!
就我而言,我有这样一家商店:
{
aa: {...},
bb: cc // the result of computing with aa
}
我需要同时更新aa
和bb
,但是bb
需要获取aa
的最新计算。
这是一些代码(React.js):
onClick(e) {
const { dispatch, aa, bb } = this.props;
dispatch(updateAa());
dispatch(updateBb(aa)); // can not get the latest computation of aa, it is the last computation..
}
那么,这是否意味着我需要在 bb
的减速器中获得 aa
?
我该怎么做?
希望得到帮助!谢谢!
有多种可能性,但鉴于代码含糊不清,很难说哪种可能性最好。
- 理想情况下,指南中描述的 your store should be normalized, meaning that each piece of data is only available in one place. Then you would calculate derived data after reading the store, such as when you use the selector pattern 将商店的状态映射到您可能认为的物化视图,该视图将作为
props
发送到您的组件。在此工作流程中,aa
和bb
将分别由选择器函数生成,而不是存储在该存储本身中。 - 您可以将更新
aa
和bb
的减速器留在combineReducers
之外,以便它看到整个状态,而不是范围缩小到 [=11= 的状态] 和bb
. - 您可以将您的计算代码提取到可以由
updateAa
和updateBb
调用的帮助程序中,并在每个操作中传递足够的信息以进行计算。 - 您可以在调度之前计算更新,以便操作包含正确的值。
问问自己是否正确构建了减速器。如果 a 和 b 不是彼此独立的,为什么它们是单独的减速器?我会尝试将它们合并成一个减速器。
不要使用 combineReducers.
例子
替换此代码
export const a = combineReducers({
app,
posts,
intl,
products,
pos,
cats,
});
和
export default (state = {}, action) => {
return {
app: app(state.app, action, state),
posts: posts(state.posts, action, state),
intl: intl(state.intl, action, state),
products: products(state.products, action, state),
pos: pos(state.pos, action, state),
cats: cats(state.cats, action, state),
};
};
reducer 会像
const reducer = (state = initialState, action, root) => {....}
正如 David L. Walsh 所说,您可能应该以更合乎逻辑的方式构建 reducer。
BUT 如果你仍然认为你需要它,你可以使用一个 thunk 中间件。 (https://github.com/gaearon/redux-thunk) Redux Thunk 中间件允许您编写 return 函数而不是动作的动作创建器。
Redux Thunk 为您提供了一种读取 Redux 存储当前状态的方法。除了调度之外,它还会将 getState 作为第二个参数传递给您 return 来自您的 thunk 动作创建者的函数。
export function action() {
return function(dispatch, getState){
const state = getState()
dispatch({
type: "ACTION_WITH_SOME_PART_OF_STATE,
some_part_of_state: state.some_part
})
}
}
如果某个reducer 需要来自另一个reducer 的一些数据,一个简单的解决方案是将它们合并到一个reducer 中。 就我而言,我需要来自另一个减速器的一些数据,而且很难管理它们,所以我最终将它们合并了。
根据 Sheikh Abdul Wahid 的回答,我不得不进行以下修改以使其适用于 history
和 connected-react-router
:
注意connectRouter(history)
()
import { connectRouter } from 'connected-react-router'
const createRootReducer = (history) => {
return (state = {}, action) => {
return {
...reducers,
router: connectRouter(history)(),
...rest of reducers
}
}
}
如果这是您的常见用例,您可以尝试编写自己的函数来根据需要组合减速器,如 official Redux documentation:
所推荐在 slice reducer 之间共享数据
类似地,如果 sliceReducerA 恰好需要 sliceReducerB 的状态切片中的一些数据来处理特定操作,或者 sliceReducerB 恰好需要整个状态作为参数,则 combineReducers 不会自行处理。这可以通过编写一个自定义函数来解决,该函数知道在这些特定情况下将所需数据作为附加参数传递,例如:
function combinedReducer(state, action) {
switch (action.type) {
case 'A_TYPICAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
b: sliceReducerB(state.b, action)
}
}
case 'SOME_SPECIAL_ACTION': {
return {
// specifically pass state.b as an additional argument
a: sliceReducerA(state.a, action, state.b),
b: sliceReducerB(state.b, action)
}
}
case 'ANOTHER_SPECIAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
// specifically pass the entire state as an additional argument
b: sliceReducerB(state.b, action, state)
}
}
default:
return state
}
}
我强烈建议您阅读 this documentation page,其中还有其他关于在 reducer 之间共享数据的建议,甚至使用 combineReducers
进行简单的操作,并在特殊情况下使用其他自定义的 reducer。
希望这些选项对您有所帮助!