Error Boundary无法捕获Apollo Client错误的问题求助
为什么你的Error Boundary没捕获到Apollo请求的错误?
问题出在Error Boundary的工作范围上:它只能捕获React渲染流程中发生的错误(比如组件渲染、生命周期方法、子组件构造函数里的错误),但你在useEffect里的client.query的catch回调中抛出的错误,属于异步代码执行错误,不在React的渲染周期内,所以Error Boundary根本感知不到,反而被create-react-app的全局错误处理机制捕获了。
解决方法:把异步错误转化为渲染时错误
要让Error Boundary捕获到这个错误,你需要把异步请求的错误转化为React渲染阶段的错误。具体来说,可以在组件中维护一个错误状态,当请求出错时更新状态,然后在渲染时根据这个状态抛出错误:
import React, { useState, useEffect } from 'react'; import ReactDOM from 'react-dom'; import ApolloClient, { gql } from 'apollo-boost'; const client = new ApolloClient({ uri: "/graphql" }); const query = gql`{ items { id }}`; class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <h1>Had error</h1> } else { return this.props.children; } } } function App() { const [data, setData] = useState(null); const [requestError, setRequestError] = useState(null); // 新增错误状态 useEffect(() => { client.query({ query }) .then(res => setData(res.data)) .catch(err => { console.warn("Error:", err); setRequestError(err); // 将错误存入状态 }); }, []); // 如果有错误,在渲染时抛出,触发Error Boundary if (requestError) { throw requestError; } return <pre>Data: {JSON.stringify(data, null, 2)}</pre>; } ReactDOM.render( <ErrorBoundary> <App /> </ErrorBoundary>, document.getElementById('root') );
这样修改后,当异步请求出错时,requestError状态会被更新,触发App组件重新渲染,此时渲染阶段抛出的错误就会被顶层的Error Boundary捕获,页面就会显示你自定义的<h1>Had error</h1>了。
补充说明
如果你不想抛出错误,也可以直接在App组件内根据requestError状态显示错误内容,但这种方式无法复用Error Boundary的统一处理逻辑。而通过在渲染时抛出错误的方式,可以让整个应用的错误都由顶层的Error Boundary统一处理,更适合大型应用的错误管理。
内容的提问来源于stack exchange,提问作者yhaskell
相关产品推荐
相关产品推荐

