Home > Software design >  Catch the errors from the thunk into the functional components React
Catch the errors from the thunk into the functional components React

Time:06-21

How can I catch the errors from async method in the thunk into the Functional Components? For example I have the following thunk:

export const updateCostCenter = (data: Record<string, unknown>) => async (dispatch: Dispatch<IWorkforceState>) => {
  dispatch(requestUpdateCostCenter());

  return api('put', `${costCenterUrl}/${data.rowId}`, data)
    .then(response => {
      return dispatch(receiveUpdateCostCenter(response.data));
    })
    .catch(err => {
      return dispatch(errorUpdateCostCenter(err.response?.data?.description));
    });
};

and in the functional component the following asynchronous method that calls the thunk:

 props.updateCostCenter(valueToSubmit).then(
        () => {
          props.showToastNotification('success', 'Successful', props.translate('cost_center_successfully_updated'));
          AmplitudeService.logEvent(props.translate('edit_cost_center'));
          props.hideDialog();
          resetForm();
          setSubmitting(false);
          if (props.loadData) {
            props.loadData();
          }
          return
        }
      ).catch(() => {
        props.showToastNotification('error', 'Error', props.translate('cost_center_update_error'))
      });

Unfortunately, I don't know why in case of error it doesn't enter into the catch from the functional component. I tried to add throw TypeError() after the dispatch of the error action, it works, but the thunk unit test fails on the pipeline.

This are the tests:

 it('update cost center success', function() {
    mockAdd.mockImplementation(
      () =>
        Promise.resolve({
            data: costCenter,
          } as any)
    );

    const expectedActions = [
      { type: WorkforceActions.REQUEST_UPDATE_COST_CENTER },
      { type: WorkforceActions.RECEIVE_UPDATE_COST_CENTER, costCenter },
    ];

    store.dispatch(updateCostCenter({ data: costCenter }) as any).then(() => {
      expect(store.getActions()).toEqual(expectedActions);
      expect(api).toHaveBeenCalled();
      return
    }).catch((unexpectedErr: any) => console.log(`Unexpectedly rejected promise ${unexpectedErr}`));
  });

  it('update cost center error', function() {
    mockAdd.mockImplementation(
      () =>
        Promise.reject({
            response: { data: { description: 'dummy-message' } },
          } as any)
    );

    const expectedActions = [
      { type: WorkforceActions.REQUEST_UPDATE_COST_CENTER },
      { type: WorkforceActions.ERROR_UPDATE_COST_CENTER, message: 'dummy-message' },
    ];

    store.dispatch(updateCostCenter({ data: costCenter }) as any).catch(() => {
      expect(store.getActions()).toEqual(expectedActions);
      expect(api).toHaveBeenCalled();
    });
  });

CodePudding user response:

Because you don't return an error.

export const updateCostCenter = (data: Record<string, unknown>) => async (dispatch: Dispatch<IWorkforceState>) => {
  dispatch(requestUpdateCostCenter());

  return api('put', `${costCenterUrl}/${data.rowId}`, data)
    .then(response => {
      dispatch(receiveUpdateCostCenter(response.data));
      return response;
    })
    .catch(err => {
      dispatch(errorUpdateCostCenter(err.response?.data?.description));
      throw err; // or throw new Error();
    });
};
  • Related