Отслеживание статуса вызовов API и сброс после завершения - PullRequest
0 голосов
/ 28 августа 2018

У меня есть следующий шаблон, который я использую, чтобы указать, когда вызов 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, равное registrationAPIOperation, и в моем наблюдаемом редуксе эпосе я обрабатываю это действие, выполняя вызов API, а затем, наконец, Я отправляю действие done из эпоса, которое устанавливает флаг success в true на редукторе операций API.

В RegPage Я проверяю, установлено ли registrationAPIOperation.success на true при обновлении реквизита, и если это так, я перенаправляю с этой страницы на другую.

Теперь одна из проблем, с которыми я сталкиваюсь, заключается в том, что если я захочу вернуться к RegPage, он обнаружит, что registrationAPIOperation.success по-прежнему верен, и немедленно перенаправит снова.

Один из способов решить эту проблему - добавить к CreateAPIOperationReducer действиям следующее:

reset: actionCreator(`${opName}/RESET`)

И обработайте это в CreateAPIOperationReducer как таковое:

case(actions.reset, state => {
      return Object.assign({}, state, initialState);
    })

Затем я могу позвонить reset, прежде чем перенаправить с RegPage, что означает, что если я вернусь к RegPage, он не будет перенаправлять.

Это хороший шаблон для подражания? Есть ли лучший способ добиться того же, где мне нужно отслеживать состояние операций API и возвращать его к исходному, как только все будет сделано?

Сложность для меня при таком подходе заключается в том, что я чувствую, как только у меня появилось несколько редукторов операций API, мне нужно будет убедиться, что к ним вызывается reset всякий раз, когда выполняется операция API (будь то успех или неудача). Не станет ли это источником потенциальных ошибок, если кто-то забудет позвонить reset в нужное время или вообще? Я чувствую, что для этого может быть более общий подход, но я не могу думать об этом.

...