10

所以,我看到一个错误,redux-promise 将错误返回给我:true,连同有效负载,但那是一旦它击中减速器......对我来说,解耦请求和错误条件有点奇怪,似乎不当。在使用带有reduc-promise(中间件)的axios时,什么是处理错误情况的有效方法..这是我所拥有的要点..

in action/
const request = axios(SOME_URL);

return {
   type: GET_ME_STUFF,
   payload: request
}

in reducer/
  const startState = {
     whatever: [],
     error: false
  }

  case GET_ME_STUFF:
     return {...state, startState, {stuff:action.payload.data, error: action.error? true : false}}

等等......然后我可以处理错误......所以,我的 api 调用现在被分成两个单独的区域,这似乎是错误的......这里一定有我遗漏的东西。我认为在 /actions 中我可以传入处理新操作等的回调,但不能拆分它。

4

6 回答 6

22

我不得不经历类似的情况。挑战在于你可能无法评估 promise 的结果,直到它在 reducer 中。你可以在那里处理你的异常,但这不是最好的模式。从我读过的内容来看,reducers 只是为了根据 action.type 返回适当的状态片段,而不做其他任何事情。

所以,输入一个额外的中间件,redux-thunk。它不是返回一个对象,而是返回一个函数,并且可以与promise共存。

它在http://danmaz74.me/2015/08/19/from-flux-to-redux-async-actions-the-easy-way/ [archived here]中得到了很好的解释。本质上,您可以在此处评估 promise 并在 promise 结果到达 reducer 之前通过其他操作创建者进行调度。

在您的操作文件中,添加将处理成功和错误(以及任何其他)状态的其他操作创建者。

function getStuffSuccess(response) {
  return {
    type: GET_ME_STUFF_SUCCESS,
    payload: response
  }
}

function getStuffError(err) {
  return {
    type: GET_ME_STUFF_ERROR,
    payload: err
  }
}

export function getStuff() {
  return function(dispatch) {
    axios.get(SOME_URL)
      .then((response) => {
        dispatch(getStuffSuccess(response))
      })
      .catch((err) => {
        dispatch(getStuffError(err))
      })
  }
}

return null

这大致是您如何将伪代码转换为链接中解释的内容。这处理直接在你的动作创建者中评估承诺,并按照动作 -> 减速器 -> 状态 -> 组件更新周期的约定向你的减速器触发适当的动作和有效负载。我自己对 React/Redux 还是很陌生,但我希望这会有所帮助。

于 2016-02-28T15:00:43.440 回答
12

接受的答案没有使用 redux-promise。由于问题实际上是关于使用 redux-promise 处理错误,我提供了另一个答案。

在 reducer 中,您应该检查 action 对象上是否存在 error 属性:

// This is the reducer
export default function(previousState = null, action) {
  if (action.error) {
    action.type = 'HANDLE_XHR_ERROR'; // change the type
  }  
  switch(action.type) {
    ...

并更改操作的类型,触发您为此设置的错误处理组件的状态更改。

你可以在 github 上阅读更多关于它的信息。

于 2017-01-13T17:48:33.057 回答
1

看起来您可以在进行分派时捕获错误,然后在发生时进行单独的错误分派。这有点骇人听闻,但它确实有效。

  store.dispatch (function (dispatch) {
      dispatch ({
        type:'FOO',
        payload:axios.get(url)
      })
      .catch (function(err) {
        dispatch ({
          type:"FOO" + "_REJECTED",
          payload:err
        });
      });
  });

在减速机中

const reducer = (state=initialState, action) => {
  switch (action.type) {
    case "FOO_PENDING": {
      return {...state, fetching: true};
    }
    case "FOO_REJECTED": {
      return {...state, fetching: false, error: action.payload};
    }
    case "FOO_FULFILLED": {
      return {
        ...state,
        fetching: false,
        fetched: true,
        data: action.payload,
      };
    }
  }
  return state;
};
于 2017-01-10T19:34:55.663 回答
1

仍然使用 redux-promises 你可以做这样的事情,我认为这是处理这个问题的一种优雅方式。

首先,在 redux 状态中设置一个属性,该属性将保存可能发生的任何 ajax 错误。

ajaxError: {},

其次,设置一个 reducer 来处理 ajax 错误:

export default function ajaxErrorsReducer(state = initialState.ajaxError, action) {
  if (action.error) {
    const { response } = action.payload;
    return {
      status: response.status,
      statusText: response.statusText,
      message: response.data.message,
      stack: response.data.stack,
    };
  }
  return state;
}

最后,创建一个非常简单的 react 组件,如果有任何错误,它将呈现错误(我正在使用 react-s-alert 库来显示漂亮的警报):

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import Alert from 'react-s-alert';

class AjaxErrorsHandler extends Component {

  constructor(props, context) {
    super(props, context);
    this.STATUS_GATE_WAY_TIMEOUT = 504;
    this.STATUS_SERVICE_UNAVAILABLE = 503;
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.ajaxError !== nextProps.ajaxError) {
      this.showErrors(nextProps.ajaxError);
    }
  }

  showErrors(ajaxError) {
    if (!ajaxError.status) {
      return;
    }
    Alert.error(this.getErrorComponent(ajaxError), {
      position: 'top-right',
      effect: 'jelly',
      timeout: 'none',
    });
  }

  getErrorComponent(ajaxError) {
    let customMessage;
    if (
      ajaxError.status === this.STATUS_GATE_WAY_TIMEOUT ||
      ajaxError.status === this.STATUS_SERVICE_UNAVAILABLE
    ) {
      customMessage = 'The server is unavailable. It will be restored very shortly';
    }
    return (
      <div>
        <h3>{ajaxError.statusText}</h3>
        <h5>{customMessage ? customMessage : ajaxError.message}</h5>
      </div>
    );
  }

  render() {
    return (
      <div />
    );
  }

}

AjaxErrorsHandler.defaultProps = {
  ajaxError: {},
};

AjaxErrorsHandler.propTypes = {
  ajaxError: PropTypes.object.isRequired,
};

function mapStateToProps(reduxState) {
  return {
    ajaxError: reduxState.ajaxError,
  };
}

export default connect(mapStateToProps, null)(AjaxErrorsHandler);

您可以将此组件包含在您的 App 组件中。

于 2017-05-25T20:57:18.260 回答
0

这可能不是最好的方法,但它对我有用。我将组件的“this”作为 var 上下文传递。然后,当我得到响应时,我只需执行在我的组件上下文中定义的方法。在我的组件中,我有successHdl 和errorHdl。从那里我可以正常触发更多的 redux 操作。我检查了所有以前的答案,对于这样一个微不足道的任务似乎太艰巨了。

export function updateJob(payload, context){

    const request = axios.put(UPDATE_SOMETHING, payload).then(function (response) {
        context.successHdl(response);
    })
    .catch(function (error) {
        context.errorHdl(error);
    });;

    return {
        type: UPDATE_SOMETHING,
        payload: payload,
    }
}
于 2016-08-18T19:22:31.047 回答
-1

不要使用 redux-promise。它使您自己做的实际上超级简单的事情变得过于复杂。

而是阅读 redux 文档:http ://redux.js.org/docs/advanced/AsyncActions.html

它将让您更好地理解如何处理这种交互,并且您将学习如何自己编写(比)redux-promise 更好的东西。

于 2016-02-28T15:17:48.710 回答