问题 如何协调Flux和React之间的服务器错误消息?


在过去的几个月里,我一直在学习React和Flux,而我还没有处理过的一件事就是向用户显示错误信息。具体而言,在flux action creator方法中由于ajax http请求而发生的错误消息。

用户登录就是一个简单的例子 - 如果由于密码错误导致ajax请求中的登录失败,则服务器会以失败进行响应。那时,在我的flux动作创建器方法中,我唯一的选择是调度包含错误信息的动作,对吧?

我可以发送错误信息并将该错误保存在商店中。但是,我不确定将某些错误绑定到某些组件的最佳方法是什么。假设我的react组件树正在呈现多个错误感知组件,但在服务器端用户身份验证尝试期间发生错误,并且需要在该登录表单上显示。

是否有良好的模式或惯例来存储错误并知道它们用于哪个组件?是否有一种编程方式来确定这一点,而不是将一些标识符传递给每个动作创建者函数,该函数标识动作创建者被称为它的组件等?


8714
2017-08-05 03:01


起源



答案:


由于您使用Redux标记标记了问题,我假设您使用Redux。
如果是这样,这个 现实世界的例子 显示错误处理。

有一个 减速器对任何动作做出反应 error 领域

// 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 action.error;
  }

  return state;
}

自定义API中间件 将任何错误消息放入 error 关于行动的领域

  return callApi(endpoint, schema).then(
    response => next(actionWith({
      response,
      type: successType
    })),
    error => next(actionWith({
      type: failureType,
      error: error.message || 'Something bad happened'
    }))
  );

最后,组件 从Redux商店读取错误消息

function mapStateToProps(state) {
  return {
    errorMessage: state.errorMessage
  };
}

如您所见,这与处理显示提取数据的方式没有任何不同。


10
2017-10-03 11:58



想象一下电子表格类型的应用程序,其中每个单元格通过ajax onblur保存。如果保存失败,用户应该看到错误消息 在无法保存的单元格中。现在,您可能会为每个单元格显示错误消息。您是否将所有这些错误保存在商店中?你如何将错误映射到单元格?谢谢你的建议。 - Jonah
假设单元格有某种ID(无论如何它们都需要用作 key 为了有效渲染),请保持 errorsByID: { id -> error } 在商店中映射。 - Dan Abramov
谢谢回复。我对这个解决方案的问题是我的密钥不是全局唯一的,而只是在他们的兄弟姐妹中是唯一的(这是允许的)。在“行”中,键只是列索引。这意味着列中的每个单元格都会显示错误。我可以使用“rowId + colIndex”作为“id” errorsById,但即便如此 那 休息,例如,如果我想在页面上渲染同一网格的两个副本。因此,“身份”在这里成为一个非常重要的问题。将一个回调传递给onError的ajax函数会直接设置组件状态是一种可怕的做法吗? - Jonah
没有什么可怕的,你没有 不得不 通过Flux路由任何东西。问题是关于Flux,但这并不意味着你必须使用它。 :-) - Dan Abramov


答案:


由于您使用Redux标记标记了问题,我假设您使用Redux。
如果是这样,这个 现实世界的例子 显示错误处理。

有一个 减速器对任何动作做出反应 error 领域

// 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 action.error;
  }

  return state;
}

自定义API中间件 将任何错误消息放入 error 关于行动的领域

  return callApi(endpoint, schema).then(
    response => next(actionWith({
      response,
      type: successType
    })),
    error => next(actionWith({
      type: failureType,
      error: error.message || 'Something bad happened'
    }))
  );

最后,组件 从Redux商店读取错误消息

function mapStateToProps(state) {
  return {
    errorMessage: state.errorMessage
  };
}

如您所见,这与处理显示提取数据的方式没有任何不同。


10
2017-10-03 11:58



想象一下电子表格类型的应用程序,其中每个单元格通过ajax onblur保存。如果保存失败,用户应该看到错误消息 在无法保存的单元格中。现在,您可能会为每个单元格显示错误消息。您是否将所有这些错误保存在商店中?你如何将错误映射到单元格?谢谢你的建议。 - Jonah
假设单元格有某种ID(无论如何它们都需要用作 key 为了有效渲染),请保持 errorsByID: { id -> error } 在商店中映射。 - Dan Abramov
谢谢回复。我对这个解决方案的问题是我的密钥不是全局唯一的,而只是在他们的兄弟姐妹中是唯一的(这是允许的)。在“行”中,键只是列索引。这意味着列中的每个单元格都会显示错误。我可以使用“rowId + colIndex”作为“id” errorsById,但即便如此 那 休息,例如,如果我想在页面上渲染同一网格的两个副本。因此,“身份”在这里成为一个非常重要的问题。将一个回调传递给onError的ajax函数会直接设置组件状态是一种可怕的做法吗? - Jonah
没有什么可怕的,你没有 不得不 通过Flux路由任何东西。问题是关于Flux,但这并不意味着你必须使用它。 :-) - Dan Abramov


你在商店中保存错误信息的想法很好(可能是一个 ErrorStore)。但是商店不需要知道对特定错误感兴趣的组件。相反, ErrorStore 需要发出一个 CHANGE 事件。发出该事件时,您可以添加一个额外的参数,即错误类型(商店可能从操作创建者那里获得)。

现在,任何组件都可以收听 ErrorStore 并检查错误类型(它将作为参数获得)。然后,组件可以知道生成了什么类型的错误,并决定他们是否对此感兴趣。


2
2017-08-05 19:29



这就是我要前往的路线。我认为就Flux-ish模式而言,这是最直接的。 - Ryan