跟踪API调用状态并完成后重置

时间:2018-08-28 19:31:20

标签: reactjs redux react-redux

我使用以下模式来指示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,这是否会成为潜在错误的来源?我觉得可以有一种更通用的方法,但是似乎没有想到。

0 个答案:

没有答案