React-Redux:我在哪里放置使用部分减速器的副作用?
React-Redux: Where do I put a side effect that uses part of a reducer?
我知道不要在 reducer 中加入副作用,而且我知道有很多关于如何处理异步操作的很好的解释。我读过它们。我有一个具体的问题,我很难过。谢谢!
我有 state.largeObject
,这是一个包含很多条目的对象。我有一个 reducer,它执行一些复杂的逻辑并将结果合并到 state.largeObject
中,如下所示:
export const myReducer = (state, { input }) => {
const largeObject = doSomethingComplex(input)
// other logic that uses largeObject
return {
...state,
largeObject: {
...state.largeObject,
...largeObject
}
}
}
我想将doSomethingComplex(input)
的结果保存到服务器。 我应该把副作用放在哪里? 编辑:不重复 doSomethingComplex
reducer 中的其他逻辑仍然需要它。
- 我不能把它放在
myReducer
或 doSomethingComplex
中,因为它们是纯的。
- 我不能把它放在 Redux 中间件中,因为它只能访问整个动作和状态。我不想在减速器和中间件中都调用
doSomethingComplex
。
- 我不想将它移动到 action-creator 中,因为这会迫使很多纯功能进入 thunk,使其更难编写。
我错过了什么?谢谢!
中间件、thunk 和商店订阅回调都是执行此操作的有效位置:
- 将一些保存逻辑作为 thunk 的一部分很好。 Thunks 是一种中间件,这就是副作用通常存在的地方。
- 您可以有一个自定义中间件来查找导致此更改的特定操作类型,或者检查此状态块是否已更改,并在状态更新后调用服务器
- 您可以有一个存储订阅回调来检查此状态块是否已更改并调用服务器
根据您的措辞方式,我不确定您是想仅发送对服务器的调用结果,还是发送{...state.largeObject, ...largeObject}
.
我认为最合适的方法是将整个 reducer 逻辑(您的 doSomethingComplex
函数)移动到服务器端。
所以您所要做的就是分派操作并将所需的参数发送到 API。如果响应成功,您将调度 success 操作,调用 myReducer
并将结果保存在商店中。
但是,如果你真的想在前端保留这个逻辑,你必须使用中间件 - thunks 或 sagas(我更喜欢 sagas)。
// some pseudo code //
dispatch the action
- inside the middleware -
call doSomethingComplex() // called once and stored in some variable
dispatch action that will call the reducer and store the result
call API with the result
但我仍然推荐第一个解决方案,因为(第二个)方法可以工作,但可能会破坏正确的数据流。
编辑:一些最后的想法 - 如果你真的想在前端保留这些计算,请考虑以下策略:
- 调度操作
- 内部中间件(thunk 或 sagas)调用
doSomethingComplex
函数
- 用 东西 调用 API
doSomethingComplex
returned
- return stuff -
doSomethingComplex
returned - 来自 API 作为 成功 响应
- 使用 stuff 调用成功操作并调用将其保存在商店中的 reducer
这就是保持正确数据流的方式。
我知道不要在 reducer 中加入副作用,而且我知道有很多关于如何处理异步操作的很好的解释。我读过它们。我有一个具体的问题,我很难过。谢谢!
我有 state.largeObject
,这是一个包含很多条目的对象。我有一个 reducer,它执行一些复杂的逻辑并将结果合并到 state.largeObject
中,如下所示:
export const myReducer = (state, { input }) => {
const largeObject = doSomethingComplex(input)
// other logic that uses largeObject
return {
...state,
largeObject: {
...state.largeObject,
...largeObject
}
}
}
我想将doSomethingComplex(input)
的结果保存到服务器。 我应该把副作用放在哪里? 编辑:不重复 doSomethingComplex
reducer 中的其他逻辑仍然需要它。
- 我不能把它放在
myReducer
或doSomethingComplex
中,因为它们是纯的。 - 我不能把它放在 Redux 中间件中,因为它只能访问整个动作和状态。我不想在减速器和中间件中都调用
doSomethingComplex
。 - 我不想将它移动到 action-creator 中,因为这会迫使很多纯功能进入 thunk,使其更难编写。
我错过了什么?谢谢!
中间件、thunk 和商店订阅回调都是执行此操作的有效位置:
- 将一些保存逻辑作为 thunk 的一部分很好。 Thunks 是一种中间件,这就是副作用通常存在的地方。
- 您可以有一个自定义中间件来查找导致此更改的特定操作类型,或者检查此状态块是否已更改,并在状态更新后调用服务器
- 您可以有一个存储订阅回调来检查此状态块是否已更改并调用服务器
根据您的措辞方式,我不确定您是想仅发送对服务器的调用结果,还是发送{...state.largeObject, ...largeObject}
.
我认为最合适的方法是将整个 reducer 逻辑(您的 doSomethingComplex
函数)移动到服务器端。
所以您所要做的就是分派操作并将所需的参数发送到 API。如果响应成功,您将调度 success 操作,调用 myReducer
并将结果保存在商店中。
但是,如果你真的想在前端保留这个逻辑,你必须使用中间件 - thunks 或 sagas(我更喜欢 sagas)。
// some pseudo code //
dispatch the action
- inside the middleware -
call doSomethingComplex() // called once and stored in some variable
dispatch action that will call the reducer and store the result
call API with the result
但我仍然推荐第一个解决方案,因为(第二个)方法可以工作,但可能会破坏正确的数据流。
编辑:一些最后的想法 - 如果你真的想在前端保留这些计算,请考虑以下策略:
- 调度操作
- 内部中间件(thunk 或 sagas)调用
doSomethingComplex
函数 - 用 东西 调用 API
doSomethingComplex
returned - return stuff -
doSomethingComplex
returned - 来自 API 作为 成功 响应 - 使用 stuff 调用成功操作并调用将其保存在商店中的 reducer
这就是保持正确数据流的方式。