我正在尝试在Typescript项目中将Immer与Redux一起使用。
Redux减速器可以键入为:
Reducer<State, Action>
我应该能够使用Immer's produce function创建一个等效的reducer,这使我们能够对草稿副本进行变异。但是类型不匹配。错误:“无法将Undefined分配给...”这可能与redux在开始时将undefined作为状态参数传递有关。如果减速器不匹配Reducer<State, Action>
,则无法将其传递给createStore
打字稿版本3.5.3。
答案 0 :(得分:1)
我还没有找到一种使之工作的方法,目前我从减速机中退回农产品
avarage: 4
答案 1 :(得分:1)
通常,produce
返回状态,因此我们不需要返回任何内容。然而,这会导致 typescript 出错,因为如果 reducer 中的任何 case 没有返回任何内容,typescript 将对其进行评估,您的 reducer 的返回值类型之一可能是 undefined
。
解决方案是在每个案例的末尾,您明确返回状态:
return state,
答案 2 :(得分:0)
使用produce
函数的咖喱形式(将函数作为第一个参数传递)时,可以为默认值传递第二个参数。当Redux在初始化时使用未定义的值调用reducer时,可以解决类型不匹配的问题。
const initState = {
text: "hello"
}
type State = {
text: string
}
type Action = {
type: "newUrl"
text: string
}
const reducer: Reducer<State, Action> = produce(
(draftSt: Draft<State>, action: Action) => {
switch(action.type){
case "newUrl":
draftSt.text = action.text
break
}
},
initState
)
然后可以将减速器安全地传递到createStore
或configureStore
。
答案 3 :(得分:0)
我遇到了同样的问题,但我记得官方zip拥有一个createReducer
助手,该助手在内部使用Immer。查看他们的代码可以提示他们如何解决此问题。
import createNextState, { Draft } from 'immer'
export function createReducer<S>(
initialState: S,
...): Reducer<S> {
...
return function(state = initialState, action): S {
// @ts-ignore createNextState() produces an Immutable<Draft<S>> rather
// than an Immutable<S>, and TypeScript cannot find out how to reconcile
// these two types.
return createNextState(state, (draft: Draft<S>) => {
const caseReducer = actionsMap[action.type]
return caseReducer ? caseReducer(draft, action) : undefined
})
}
}
(请参见Redux Toolkit。为简洁起见,我用“ ...”缩短了不相关的部分)。
您可以在这里看到他们的辅助函数返回一个结构正常的化合器,其主要工作是将state
传递给createNextDraft
函数。有趣的是,这只是从Immer导入default
,因此它只是produce
函数的别名。
有关如何使用此功能的示例,请参见下文:
import produce, { Draft } from 'immer';
const reducer: Reducer<State, AnyAction> = (state: State = initialState, action: AnyAction) => {
return produce(state, (draft: Draft<State>) => {
switch (action.type) {
case 'Execute':
draft.isFetching = true;
break;
case 'Success':
draft.isFetching = false;
break;
case 'Failure':
draft.isFetching = false;
break;
}
});
答案 4 :(得分:0)
这对我有用:
import produce from 'immer';
const reducer = (state = initialState, action: AnyAction) : State => {
return produce(state, (draft) => {
switch (action.type) {
case 'Execute':
draft.isFetching = true;
break;
case 'Success':
draft.isFetching = false;
break;
case 'Failure':
draft.isFetching = false;
break;
default:
draft;
}
});
export default reducer;