小能豆

处理 React Redux 中的获取错误的最佳方法是什么?

javascript

我有一个用于客户端的reducer,另一个用于AppToolbar,还有一些其他的…

现在假设我创建了一个获取操作来删除客户端,如果它失败了,我在客户端减速器中有一些代码应该做一些事情,但我也想在 AppToolbar 中显示一些全局错误。

但是客户端和 AppToolbar 减速器不共享状态的同一部分,因此我无法在减速器中创建新的动作。

那么我应该如何显示全局错误?谢谢

更新 1:

我忘了说我用的是este devstack

更新 2: 我将 Eric 的答案标记为正确,但我不得不说,我在本例中使用的解决方案更像是 Eric 和 Dan 的答案的组合......您只需要在代码中找到最适合您的内容......


阅读 28

收藏
2024-06-12

共1个答案

小能豆

在 Redux 应用程序中使用单独的 Reducer 来处理状态的不同部分,处理全局错误确实很有挑战性。以下是处理这种情况的结构化方法:

  1. 定义全局错误操作: 创建处理全局错误的操作。任何操作(例如删除客户端)发生错误时,都会分派这些操作。
  2. 创建全局错误 Reducer: 创建专用于处理全局错误的 Reducer。此 Reducer 将监听全局错误操作并更新全局错误状态。
  3. 处理 Thunk 或 Sagas 中的错误: 使用 Redux Thunk 或 Redux Saga 等中间件来处理异步操作,并在发生错误时分派全局错误操作。

逐步实施

1. 定义全局错误操作

// actionTypes.js
export const DELETE_CLIENT_FAILURE = 'DELETE_CLIENT_FAILURE';
export const GLOBAL_ERROR = 'GLOBAL_ERROR';

// actionCreators.js
export const deleteClientFailure = (error) => ({
  type: DELETE_CLIENT_FAILURE,
  error,
});

export const globalError = (error) => ({
  type: GLOBAL_ERROR,
  error,
});

2. 创建一个全局错误减少器

// globalErrorReducer.js
import { GLOBAL_ERROR } from './actionTypes';

const initialState = {
  message: null,
};

const globalErrorReducer = (state = initialState, action) => {
  switch (action.type) {
    case GLOBAL_ERROR:
      return {
        ...state,
        message: action.error,
      };
    default:
      return state;
  }
};

export default globalErrorReducer;

3. 结合 Reducer

结合使用你的减速器combineReducers来包含全局错误减速器:

// rootReducer.js
import { combineReducers } from 'redux';
import clientsReducer from './clientsReducer';
import appToolbarReducer from './appToolbarReducer';
import globalErrorReducer from './globalErrorReducer';

const rootReducer = combineReducers({
  clients: clientsReducer,
  appToolbar: appToolbarReducer,
  globalError: globalErrorReducer,
});

export default rootReducer;

4. 处理 Thunk 或 Sagas 中的错误

如果您使用 Redux Thunk,请在异步操作中处理错误并分派全局错误操作:

// clientActions.js
import { deleteClientFailure, globalError } from './actionCreators';

export const deleteClient = (clientId) => {
  return async (dispatch) => {
    try {
      // Assume deleteClientApi is a function that deletes a client
      await deleteClientApi(clientId);
      // Dispatch success action if needed
    } catch (error) {
      dispatch(deleteClientFailure(error.message));
      dispatch(globalError('Failed to delete client. Please try again.'));
    }
  };
};

如果您使用 Redux Saga,请在 saga 中以类似的方式处理错误:

// clientSagas.js
import { call, put, takeEvery } from 'redux-saga/effects';
import { DELETE_CLIENT_REQUEST, deleteClientFailure, globalError } from './actionCreators';
import { deleteClientApi } from './api';

function* deleteClientSaga(action) {
  try {
    yield call(deleteClientApi, action.payload.clientId);
    // Dispatch success action if needed
  } catch (error) {
    yield put(deleteClientFailure(error.message));
    yield put(globalError('Failed to delete client. Please try again.'));
  }
}

export function* watchDeleteClient() {
  yield takeEvery(DELETE_CLIENT_REQUEST, deleteClientSaga);
}

5.显示全局错误

将您的AppToolbar组件连接到全局错误状态并显示错误消息(如果存在):

// AppToolbar.js
import React from 'react';
import { connect } from 'react-redux';

const AppToolbar = ({ errorMessage }) => (
  <div>
    {errorMessage && <div className="error-message">{errorMessage}</div>}
    {/* Other toolbar contents */}
  </div>
);

const mapStateToProps = (state) => ({
  errorMessage: state.globalError.message,
});

export default connect(mapStateToProps)(AppToolbar);

此设置可确保错误可以全局处理并显示在AppToolbar组件中,而无需紧密耦合您的 Reducer。每个 Reducer 都专注于其自己的状态部分,而全局错误状态则处理整个应用程序的错误。

2024-06-12