簡體   English   中英

處理 react redux 中的獲取錯誤的最佳方法是什么?

[英]What is the best way to deal with a fetch error in react redux?

我有一個用於客戶端的減速器,另一個用於 AppToolbar 和其他一些......

現在假設我創建了一個獲取操作來刪除客戶端,如果它失敗了,我在 Clients reducer 中有代碼應該做一些事情,但我也想在 AppToolbar 中顯示一些全局錯誤。

但是客戶端和 AppToolbar reducers 不共享相同的狀態部分,我無法在 reducer 中創建新的操作。

那么我應該如何顯示全局錯誤呢? 謝謝

更新 1:

我忘了說我用的是este devstack

更新 2:我將埃里克的答案標記為正確,但我不得不說我在埃斯特使用的解決方案更像是埃里克和丹的答案的組合......你只需要在你的代碼中找到最適合你的東西...... .

如果你想擁有“全局錯誤”的概念,你可以創建一個errors reducer,它可以監聽 addError、removeError 等操作。 然后,您可以在state.errors掛鈎到您的 Redux 狀態樹,並在適當的地方顯示它們。

有很多方法可以解決這個問題,但一般的想法是全局錯誤/消息應該有自己的 reducer 以完全獨立於<Clients /> / <AppToolbar /> 當然,如果這些組件中的任何一個需要訪問errors ,您可以在需要時將errors作為 prop 傳遞給它們。

更新:代碼示例

這是一個示例,說明如果將“全局錯誤” errors傳遞到頂級<App />並有條件地呈現它(如果存在錯誤),它可能會是什么樣子。 使用react-redux 的connect將你的<App />組件連接到一些數據。

// App.js
// Display "global errors" when they are present
function App({errors}) {
  return (
    <div>
      {errors && 
        <UserErrors errors={errors} />
      }
      <AppToolbar />
      <Clients />
    </div>
  )
}

// Hook up App to be a container (react-redux)
export default connect(
  state => ({
    errors: state.errors,
  })
)(App);

就 action creator 而言,它會根據響應分派 ( redux-thunk ) success failure

export function fetchSomeResources() {
  return dispatch => {
    // Async action is starting...
    dispatch({type: FETCH_RESOURCES});

    someHttpClient.get('/resources')

      // Async action succeeded...
      .then(res => {
        dispatch({type: FETCH_RESOURCES_SUCCESS, data: res.body});
      })

      // Async action failed...
      .catch(err => {
        // Dispatch specific "some resources failed" if needed...
        dispatch({type: FETCH_RESOURCES_FAIL});

        // Dispatch the generic "global errors" action
        // This is what makes its way into state.errors
        dispatch({type: ADD_ERROR, error: err});
      });
  };
}

雖然您的減速器可以簡單地管理一系列錯誤,適當地添加/刪除條目。

function errors(state = [], action) {
  switch (action.type) {

    case ADD_ERROR:
      return state.concat([action.error]);

    case REMOVE_ERROR:
      return state.filter((error, i) => i !== action.index);

    default:
      return state;
  }
}

Erik 的回答是正確的,但我想補充一點,您不必為添加錯誤而觸發單獨的操作。 另一種方法是使用一個 reducer 來處理帶有error字段的任何操作 這是個人選擇和慣例的問題。

例如,來自具有錯誤處理的Redux real-world示例

// Updates error message to notify about the failed fetches.
function errorMessage(state = null, action) {
  const { type, error } = action

  if (type === ActionTypes.RESET_ERROR_MESSAGE) {
    return null
  } else if (error) {
    return error
  }

  return state
}

我目前針對一些特定錯誤(用戶輸入驗證)采用的方法是讓我的子化簡器拋出異常,在我的根化簡器中捕獲它,並將其附加到操作對象。 然后我有一個 redux-saga,它檢查動作對象是否有錯誤,並在這種情況下用錯誤數據更新狀態樹。

所以:

function rootReducer(state, action) {
  try {
    // sub-reducer(s)
    state = someOtherReducer(state,action);
  } catch (e) {
    action.error = e;
  }
  return state;
}

// and then in the saga, registered to take every action:
function *errorHandler(action) {
  if (action.error) {
     yield put(errorActionCreator(error));
  }
}

然后按照 Erik 的描述將錯誤添加到狀態樹。

我很少使用它,但它使我不必復制合法屬於 reducer 的邏輯(因此它可以保護自己免受無效狀態的影響)。

編寫自定義中間件來處理所有與 api 相關的錯誤。 在這種情況下,您的代碼會更簡潔。

   failure/ error actin type ACTION_ERROR

   export default  (state) => (next) => (action) => {

      if(ACTION_ERROR.contains('_ERROR')){

       // fire error action
        store.dispatch(serviceError());

       }
}

我所做的是在每個效果的基礎上集中處理效果中的所有錯誤

/**
 * central error handling
 */
@Effect({dispatch: false})
httpErrors$: Observable<any> = this.actions$
    .ofType(
        EHitCountsActions.HitCountsError
    ).map(payload => payload)
    .switchMap(error => {
        return of(confirm(`There was an error accessing the server: ${error}`));
    });

您可以使用 axios HTTP 客戶端。 它已經實現了攔截器功能。 您可以在請求或響應被 then 或 catch 處理之前攔截它們。

https://github.com/mzabriskie/axios#interceptors

 // Add a request interceptor axios.interceptors.request.use(function (config) { // Do something before request is sent return config; }, function (error) { // Do something with request error return Promise.reject(error); }); // Add a response interceptor axios.interceptors.response.use(function (response) { // Do something with response data return response; }, function (error) { // Do something with response error return Promise.reject(error); });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM