Reactjs 为什么不应该';我是否使用catch()来处理React-useEffect API调用中的错误?

Reactjs 为什么不应该';我是否使用catch()来处理React-useEffect API调用中的错误?,reactjs,react-hooks,use-effect,Reactjs,React Hooks,Use Effect,在React文档的此页上: 代码注释说 注意:在这里处理错误而不是catch()块很重要,这样我们就不会从组件中的实际错误中吞下异常 …关于处理第二个的第二个参数中的错误。然后在fetch之后处理。文档中的完整片段是: useffect(()=>{ 取回(“https://api.example.com/items") .then(res=>res.json()) .那么( (结果)=>{ setIsLoaded(真); 设置项目(结果); }, //注意:这里处理错误很重要 //而不是一个c

在React文档的此页上:

代码注释说

注意:在这里处理错误而不是catch()块很重要,这样我们就不会从组件中的实际错误中吞下异常

…关于处理第二个
的第二个参数中的错误。然后在
fetch
之后处理
。文档中的完整片段是:

useffect(()=>{
取回(“https://api.example.com/items")
.then(res=>res.json())
.那么(
(结果)=>{
setIsLoaded(真);
设置项目(结果);
},
//注意:这里处理错误很重要
//而不是一个catch()块,这样我们就不会吞咽
//组件中实际错误的例外情况。
(错误)=>{
setIsLoaded(真);
设置错误(错误);
}
)
}, [])
它没有详细说明这个建议,我已经看到许多使用
catch
处理API调用错误的React代码示例。我尝试过谷歌搜索,但找不到任何澄清

有人能给我一个更详细的解释,为什么我不应该使用
catch
来处理在
useffect
钩子中进行
fetch
API调用时出现的错误

或者在某些情况下可以这样做,但在其他情况下不行

组件中的“吞咽异常[…]是什么意思”

此规则/指南是否适用于所有React,还是仅适用于API调用


或者只需使用
useffect
hook或
componentDidMount
lifecycle方法?

我能找到的一切似乎都可以追溯到2016年左右。我将逐字引用其中的内容,因为以前似乎没有在堆栈溢出中介绍过它,并且它非常彻底地解释了这一点:


您的
catch()
处理程序将捕获
then()中抛出的任何错误
之前的链,包括由于
setState()
调用

即使您不直接使用
setState
,也可能会遇到同样的问题 如果您调用的其他代码使用它(例如,Redux
dispatch()

如果您不想捕获由
setState()
引起的错误,并且希望 只捕获网络故障(让我们想象一下您的
Promise.resolve()
实际上是一个
fetch()
),您想使用第二个
then()
参数 相反:

在这种情况下,除非在链的后面执行
catch()
,否则
render()
将是未捕获的,并且具有良好的承诺polyfill(或 Chrome和其他浏览器中的本机承诺),显示


编辑:根据@Martin的回答,我去测试了这一点,我可以确认这似乎不再是一个相关问题。从v16.0起,React的任何版本都不会捕捉到来自
setState
的渲染错误,而且由于
useState
仅在v16.8中引入,因此这似乎不可能成为挂钩的问题


下面是一个示例,演示了旧版本React中的原始问题。

这是示例作者的复制粘贴错误。 第一个示例使用基于类的组件的组件状态:
this.setState()
导致同步重新呈现(或者至少2016年的react v15.0就是这种情况,不确定它今天是否成立)。因此,警告注释和使用第二个参数
。然后(onResolve,onReject)
是合理的。 第二个示例使用函数组件的
useState
钩子:
setState
不会导致同步重新渲染,只会导致异步重新渲染。因此,警告注释和使用第二个参数来
。然后(onResolve,onReject)
不合理的

为了说明这一点:使用
useState
hooks,您可以调用多个更新程序,它们只在一次重新渲染中生效

const [a, setA] = useState();
const [b, setB] = useState();
const [c, setC] = useState();

const updateState = () => {
  setA('foo');
  setB('bar');
  setC('buz');
  // will only cause one single re-render
}
因此,使用catch是非常好的

useEffect(() => {
    fetch("https://api.example.com/items")
      .then(res => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setItems(result);
        }
      )
      .catch(
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      )
  }, [])

因此,如果我理解正确,那么这个注释是错误地留在示例中的,我完全没有理由不使用catch()来处理React-useEffect API调用中的错误。太好了,谢谢。是的,没错。您可以使用
.catch()
,我认为这可以提高代码的清晰度。感谢您回答我的问题,并测试和确认其他答案。
const [a, setA] = useState();
const [b, setB] = useState();
const [c, setC] = useState();

const updateState = () => {
  setA('foo');
  setB('bar');
  setC('buz');
  // will only cause one single re-render
}
useEffect(() => {
    fetch("https://api.example.com/items")
      .then(res => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setItems(result);
        }
      )
      .catch(
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      )
  }, [])