Reactjs React Redux中错误处理的正确方法

Reactjs React Redux中错误处理的正确方法,reactjs,redux,Reactjs,Redux,我想了解使用React Redux处理错误的更一般或正确的方法 假设我有电话号码注册组件 const ExampleErrorComponent= () => { const error = useSelector(selectError); if (!error) return null; return <div className="error-message">{error}</div>; } 如果输入的电话号码无效,该组件将抛出一个错误 处理该

我想了解使用React Redux处理错误的更一般或正确的方法

假设我有电话号码注册组件

const ExampleErrorComponent= () => {
  const error = useSelector(selectError);
  if (!error) return null;
  return <div className="error-message">{error}</div>;
}
如果输入的电话号码无效,该组件将抛出一个错误

处理该错误的最佳方法是什么

想法1: 创建一个组件,该组件接受错误并在错误传递给它时分派操作

想法2: 由于错误与该组件相关,请将该错误传递给一个组件(该组件未连接到redux,即错误处理程序组件不会分派该操作)


问题:有人能指导我如何正确处理React Redux中的大规模应用程序错误吗

我想说的是,你最初的两个想法都没有抓住全局。想法1只是一个回调。如果要使用回调:
useCallback
。如果您不需要使用redux,则想法2将起作用,并且更可取。有时候你最好使用redux。也许您是通过检查所有输入字段都没有错误或类似的内容来设置表单有效性。既然我们讨论的是redux,那么让我们假设情况就是这样

通常,使用redux处理错误的最佳方法是使错误字段处于状态,然后将其传递给错误组件

const ExampleErrorComponent= () => {
  const error = useSelector(selectError);
  if (!error) return null;
  return <div className="error-message">{error}</div>;
}
2.如果后端报告错误,则分派错误操作。 假设您正在将电话号码发送到后端,该后端在对该号码进行处理之前进行验证。您无法知道数据在客户端是否有效。你只要听服务器的话就行了

const handleSubmit = useCallback(
  () => sendPhoneNumber(phoneNumber)
    .then(response => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_SUCCESS',
      response,
    }))
    .catch(error => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_FAILURE',
      error,
    })),
  [dispatch, phoneNumber],
);
然后,减速器应该为错误提供适当的消息并进行设置

别忘了取消设置错误。根据应用程序的不同,您可以在更改操作或发出其他请求时取消设置错误


我概述的两种方法并不是相互排斥的。您可以使用第一个来显示本地可检测的错误,也可以使用第二个来显示服务器端或网络错误。

我将使用带有yup验证的formik。 然后,对于服务器端错误,我将使用如下内容:

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Spinner } from "@blueprintjs/core";

export default ({ action, selector, component, errorComponent }) => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(action());
  }, [dispatch, action]);

  const DispatchFetch = () => {
    const { data, isRequesting, error } = useSelector(selector());
    if (!isRequesting && data) {
      const Comp = component;
      return <Comp data={data}></Comp>;
    } else if (error) {
      if (errorComponent) {
        const ErrorComp = errorComponent;
        return <ErrorComp error={error}></ErrorComp>;
      }
      return <div>{error}</div>;
    }
    return <Spinner></Spinner>;
  };

  return <DispatchFetch></DispatchFetch>;
};
import React,{useffect}来自“React”;
从“react redux”导入{useDispatch,useSelector};
从“@blueprintjs/core”导入{Spinner};
导出默认值({action,selector,component,errorComponent})=>{
const dispatch=usedpatch();
useffect(()=>{
调度(action());
},[派遣、行动];
const DispatchFetch=()=>{
const{data,isRequesting,error}=useSelector(selector());
if(!isRequesting&&data){
常数Comp=组件;
返回;
}else if(错误){
if(错误组件){
常量ErrorComp=errorComponent;
返回;
}
返回{error};
}
返回;
};
返回;
};

这取决于您所说的错误处理类型。如果这只是表单验证处理,那么我认为您不需要Redux来实现这一点-请阅读。如果您的错误只会在该组件中被“消耗”,为什么要将其发送到redux?你可以很容易地利用你当地的州来做这件事

另一方面,如果您想向用户显示某种错误通知,指示站点上的任何HTTP调用是否失败,您可以通过从应用程序的所有部分(甚至是一般的中间件)分派错误来使用redux


您需要定义如何组织您的状态,以及是否需要在redux中放置一些状态,或者只是将其保持在组件的本地状态。你可以把所有的东西都放在redux中,但我个人认为这是一种过分的做法——如果只有组件Y关心状态,为什么还要把状态X放在组件Y中呢?如果你的代码结构正确,那么你以后将该状态从本地移动到redux不会有问题,如果出于某种原因,你的应用程序的其他部分开始依赖于该状态。

我这样想,状态应该是什么?从国家中应该得到什么? 状态应该存储在redux中,并且应该计算派生

电话号码是state,具有焦点的字段是state,但不管它是否有效,都可以从state中的值派生出来

我将使用重新选择来缓存派生,并在相关状态未被修改时返回相同的结果

export const showInvalidPhoneNumberMessage = createSelector(
  getPhoneValue,
  getFocusedField,
  (val, focus) => focus !== 'phone' && val.length < 10 // add other validations.
)
export const showInvalidPhoneNumberMessage=createSelector(
getPhoneValue,
getFocusedField,
(val,focus)=>focus!='phone'和&val.length<10//添加其他验证。
)
然后,您可以在所有可能关心此值的组件中使用MapStateTops中的选择器,也可以在异步操作中使用它。如果焦点没有改变,或者字段的值没有改变,则不会重新计算,而是返回上一个值

我添加了selectedstate检查,只是为了显示多个状态如何组合在一起,从而产生一个派生


我个人试图通过尽可能保持我的状态来处理事情。例如,假设您想创建自己的日历。你会把每一天都储存在州里吗?还是你只需要知道一些事情,比如当前正在查看的年份和月份。仅使用这两种状态,您就可以计算日历上显示的天数,并且在其中一种状态发生变化之前无需重新计算,而这种重新计算几乎会自动进行,无需考虑它们可能发生变化的所有方式。

如何同步或异步验证电话号码,在用户做某事之后还是立即?您希望发生什么,对用户可见?Redux用于存储应用程序的状态,它似乎与您的问题无关。我非常感谢您的回答,与我的做法相比,这显然是一种更好的方法。我仍然在寻找更多的建议和建议
export const showInvalidPhoneNumberMessage = createSelector(
  getPhoneValue,
  getFocusedField,
  (val, focus) => focus !== 'phone' && val.length < 10 // add other validations.
)