首页 文章

React Redux normalizr api请求错误处理

提问于
浏览
2

我已经为我的应用程序中的每个API调用实现了一个抽象的“实体”缩减器 . 现在我想使用normalizr来保持API数据的标准化形状 . 到目前为止,我正在保存我的API请求响应,它来自API动作的API中间件,在reducer中:

case action.type.includes(API_ERROR):
case action.type.includes(API_SUCCESS):
  return {
    ...state,
    [action.payload.label]: {
      error: action.isError,
      data: action.payload.data
    }
  };

to keep my Error flag 能够指示(在组件中)请求是否成功 .

如果我正确理解normalizr,那么实体reducer将被视为"database" . 我想在标准化数据中使用 errorisError 标志是不对的?

我只是无法解决,当我使用normalizr来规范化数据时我的Reducer将如何显示以及如果请求成功或不在此代码重构之后我将如何跟踪(在组件中......)

另一件事是,如果我的请求失败,响应数据将不包含ID或任何其他标识,告知哪些请求失败(我当前正在使用实体标签,例如,fetchMembers()操作作为指示器) . 失败的响应数据仅包含状态和原因(原因) .

你们有什么建议吗?我可以继续只使用单个抽象减速器吗,或者我应该为我的所有API操作更好地制作自定义减速器?

SUBQUESTION:

而且我在组件的上下文中也是 having requests, which response data are not significant ,如果请求SUCCED或FAILED(请求如注销,登录,......),则只有重要信息 . 我假设他们的回复不应该分配给redux商店以防止商店膨胀 . 请问这些请求怎么办?

1 回答

  • 2

    不要在规范化数据中放置isError或isLoading标志,因为normalizr用于规范化深层嵌套对象 . 它本质上是一个深度嵌套的javascript对象并将其展平,这样你就可以摆脱冗余数据,这是它最大的优势 . 我们使用了React Redux-Sagas normalizr . 希望这段代码可以帮助您设置减速机

    Reducer

    // @flow
    
    import {
      FETCH_DETAILED_EXPERIENCE_DATA,
      FETCH_DETAILED_EXPERIENCE_DATA_SUCCESS,
      FETCH_DETAILED_EXPERIENCE_DATA_ERROR,
    } from '../ActionTypes'
    import Immutable from 'seamless-immutable'
    import { createReducer } from '../CreateReducer'
    
    const INITIAL_STATE = Immutable({
      experienceData: null,
      isFetching: false,
      error: null,
    })
    
    const reducers = {
      [FETCH_DETAILED_EXPERIENCE_DATA]: (state, action) => {
        return Immutable.merge(state, { experienceData: null, isFetching: true })
      },
      [FETCH_DETAILED_EXPERIENCE_DATA_SUCCESS]: (state, { data }) => {
        return Immutable.merge(state, { experienceData: data, isFetching: false, error: null })
      },
      [FETCH_DETAILED_EXPERIENCE_DATA_ERROR]: (state, { error }) => {
        return Immutable.merge(state, { error, isFetching: false })
      },
    }
    
    export const reducer = createReducer(INITIAL_STATE, reducers)
    

    Sagas

    import { FETCH_DETAILED_EXPERIENCE_DATA } from '../ActionTypes'
    import { put, takeLatest, call } from 'redux-saga/effects'
    import API from '../../Services/baseApi'
    import * as ExperienceActions from './Actions'
    import * as EntitiesActions from '../entities/Actions'
    
    import parseExperienceDetailResponse from 'App/Schemas/APIResponse/ExperienceDetailResponse'
    
    function* fetchExperienceDetails(action) {
      try {
        const response = yield call(API.get, 'URL')
        const { entities, result } = parseExperienceDetailResponse(response.data)
        yield put(EntitiesActions.updateEntities(entities))
        yield put(ExperienceActions.fetchDetailedExperienceSuccess(result))
      } catch (e) {
        yield put(ExperienceActions.fetchDetailedExperienceError(e.message))
      }
    }
    
    export default function* root() {
      yield [yield takeLatest(FETCH_DETAILED_EXPERIENCE_DATA, fetchExperienceDetails)]
    

    Schema

    // @flow
    
    import { normalize, schema } from 'normalizr'
    
    const experience = new schema.Entity(
      'experiences',
      {
        owner: user,
      },
      { idAttribute: 'Id' },
    )
    
    
    const response = new schema.Object({
      experience,
    })
    
    export default (input: any) => {
      const { entities, result } = normalize(input, response)
    
      return {
        entities,
        result: result,
      }
    }
    

    希望这有助于谢谢 .

相关问题