我使用以下模式来指示API调用何时开始,成功或失败:
import actionCreatorFactory from "typescript-fsa";
import { reducerWithInitialState } from "typescript-fsa-reducers";
export interface IAPIOperation<TFailurePayload> {
pending: boolean;
success: boolean;
failure: boolean;
error: TFailurePayload;
}
const CreateAPIOperationReducer = <
TStartPayload,
TSuccessPayload,
TFailurePayload
>(
opName: string,
failurePayloadInitialState: TFailurePayload
) => {
const initialState: IAPIOperation<TFailurePayload> = {
pending: false,
success: false,
failure: false,
error: failurePayloadInitialState
};
const actionCreator = actionCreatorFactory();
const actions = {
...actionCreator.async<TStartPayload, TSuccessPayload, TFailurePayload>(
opName
)
};
const reducer = reducerWithInitialState(initialState)
.case(actions.started, (state, _PAYLOAD) => {
return Object.assign({}, state, initialState, {
pending: true
});
})
.case(actions.done, (state, _PAYLOAD) => {
return Object.assign({}, state, initialState, {
success: true
});
})
.case(actions.failed, (state, payload) => {
return Object.assign({}, state, initialState, {
failure: true,
error: payload
});
});
return {
reducer,
actions: {
started: actions.started,
done: actions.done,
failed: actions.failed,
},
initialState
};
};
export default CreateAPIOperationReducer;
在我的实际化简器中,我使用CreateAPIOperationReducer
并将其与我的实际化简器组合在一起,以便我可以跟踪与化简器状态相关的API调用:
import { combineReducers } from "redux";
import { reducerWithInitialState } from "typescript-fsa-reducers";
import createAPIOperationReducer, { IAPIOperation } from "./APIOperation";
export interface IRegistration {
registrationUrl: string;
}
const initialRegState: IRegistration = {
registrationUrl: ""
};
export interface IRegistrationState {
registration: IRegistration;
registrationAPIOperation: IAPIOperation<string>;
}
export const registerAPIOperation = createAPIOperationReducer<
string,
string,
string
>("REGISTER", "");
export const actions = {
registerAPIOperationActions: {
...registerAPIOperation.actions
}
};
export const initialState: IRegistrationState = {
registration: initialRegState,
registrationAPIOperation: registerAPIOperation.initialState
};
const registration = reducerWithInitialState(initialRegState).case(
actions.registerAPIOperationActions.done,
(state, payload) => {
return Object.assign({}, state, {
registrationUrl: payload.result
});
}
);
export default combineReducers<IRegistrationState>({
registration,
registrationAPIOperation: registerAPIOperation.reducer
});
在我的一个容器页面(称为RegPage
)中,我调度了started
的{{1}}动作,在我的Redux可观察的史诗中,我通过API调用,然后最后我从史诗中调度registrationAPIOperation
操作,该操作将API操作reducer上的done
标志设置为true。
在success
中,我检查道具更新时RegPage
是否设置为registrationAPIOperation.success
,如果是,则将其从该页面重定向到另一个页面。
现在我遇到的问题之一是,如果我想回到true
,它将检测到RegPage
仍然为真,并立即再次重定向。
我想解决这个问题的一种方法是在registrationAPIOperation.success
动作中添加以下内容:
CreateAPIOperationReducer
并按如下方式在reset: actionCreator(`${opName}/RESET`)
中进行处理:
CreateAPIOperationReducer
然后我可以在从case(actions.reset, state => {
return Object.assign({}, state, initialState);
})
重定向之前呼叫reset
,这意味着如果我回到RegPage
,它将不会重定向。
这是遵循的好模式吗?是否有更好的方法来实现相同的目的,我需要跟踪API操作的状态,并在完成所有操作后将其重置为初始状态?
使用这种方法给我带来的痛苦是,我觉得一旦我有几个API操作简化程序,我将需要确保在API操作完成时(无论成功与否)都在它们上调用RegPage
)。如果有人忘记在适当的时间致电reset
或根本忘记致电reset
,这是否会成为潜在错误的来源?我觉得可以有一种更通用的方法,但是似乎没有想到。