使用 Axios 和 Redux 添加错误状态

Adding an error state with Axios and Redux

我在让我的应用程序按我希望的方式运行时遇到了一些麻烦。我对 React 和 Redux 还很陌生,所以请多多包涵。

现在我可以调用 this.props.fetchData('usernamehere') 来获取有关用户的一些数据,当它成功时它会更新 this.props.profile,我用它来更新 React 组件。问题在于处理错误。

我试图通过添加一个 FETCH_DATA_ERROR reducer 来解决这个问题,但我遇到的问题是当它出现 404 时它仍然用一个空对象替换 this.props.profile 而不是仅仅更新this.props.error。理想情况下,我想保留当前的配置文件,直到它成功找到新的配置文件,然后通过更新 this.props.error 向用户显示他们输入的用户名有什么错误。

现在我有以下动作创建器设置:

import axios from 'axios';
import { FETCH_DATA, FETCH_DATA_ERROR } from './types';

export const ROOT_URL = 'https://api.github.com/users'

export function fetchData(user) {
  const request = axios.get(`${ROOT_URL}/${user}`)
  .catch(function (error) {
    return {
      type: FETCH_DATA_ERROR,
      payload: error
    }
  });

  return {
    type: FETCH_DATA,
    payload: request
  }
}

和减速器:

import { FETCH_DATA, FETCH_DATA_ERROR } from '../actions/types';

const INITIAL_STATE = { profile: null, error: null }

export default function(state = INITIAL_STATE, action) {
  switch(action.type) {
    case FETCH_DATA:
      return { ...state, profile: action.payload.data };

    case FETCH_DATA_ERROR:
      return { ...state, error: action.payload };

  default:
    return state;
  }
}

如果有人有任何建议,我们将不胜感激。我觉得我在正确的道路上,但似乎无法弄清楚我哪里错了。

到目前为止,您有一个表示请求开始的操作 (FETCH_DATA) 和一个表示请求失败的操作 (FETCH_DATA_ERROR)。通常这是用第三个模型建模的,表示请求产生了积极响应(可能 FETCH_DATA_SUCCESS)。

您需要使用 https://github.com/gaearon/redux-thunk 之类的东西重写您的 action creator,以便它首先仅发送 FETCH_DATA,然后在 axios.get 的 then/catch-handlers 中发送成功或失败的操作:

import { FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_ERROR } from '../actions/types';

// ASYNC ACTION CREATOR

export const fetchData = user => (dispatch) => {
    dispatch({
        type: FETCH_DATA
    });

    return axios.get(`${ROOT_URL}/${user}`)
        .then(response => dispatch({
            type: FETCH_DATA_SUCCESS,
            payload: response
        }))
        .catch(error => dispatch({
            type: FETCH_DATA_ERROR,
            payload: error
        }));
};


// REDUCER

const INITIAL_STATE = {
    profile: null,
    error: null
};

export default function(state = INITIAL_STATE, action) {
    switch(action.type) {
        // Start of request - discard old data and reset old errors.  
        case FETCH_DATA:
            return {
            // It's important to set all of these to properly model the request lifecycle
            // and avoid race conditions etc.
            profile: null,
            error: null
        };

        // End of request - save profile and signal that there was no error.
        case FETCH_DATA_SUCCESS:
            return {
                profile: action.payload.data,
                error: null
            };

        // End of request - discard old profile and save error, to display it to the user for example.
        case FETCH_DATA_ERROR:
            return {
                profile: null,
                error: action.payload
            };

        default:
            return state;
    }
}