错误边界不捕获来自 apollo 客户端的错误
Error boundary doesn't catch error from apollo client
我试图在顶层捕获一些错误,以展示世界上最漂亮的错误页面。
出于某种原因,我看到我的节点已断开连接,但错误边界从未触发。
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: any) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Had error</h1>
} else {
return this.props.children;
}
}
}
function App() {
const [data, setData] = useState<any>(null);
useEffect(() => {
client.query({ query })
.then(res => setData(res))
.catch(err => { console.warn("Error:", err); throw err; });
}, []);
return <pre>Data: {data}</pre>;
}
ReactDOM.render(
<ErrorBoundary>
<App />
</ErrorBoundary>,
document.getElementById('root')
);
我 运行 这是在一个空的 create-react-app 项目中。
我希望看到<h1>Had error</h1>
;我收到 CRA 未处理的错误屏幕。
来自docs
Error boundaries do not catch errors for:
- Event handlers (learn more)
- Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
- Server side rendering
- Errors thrown in the error boundary itself (rather than its children)
Promise 是异步的,因此被拒绝的 Promises 不会被错误边界捕获。目前,recommended but somewhat hackish approach 是在setState
中抛出错误。在功能组件中,您可以使用由 useState
钩子编辑的设置函数 return 代替 setState
:
const [, setState] = useState()
useEffect(() => {
client.query({ query })
.then(res => setData(res))
.catch(err => {
console.warn("Error:", err);
setState(() => {
throw err;
});
});
}, []);
在 useEffect
中抛出也可以,但在 Promise 的 then
或 catch
回调中不行。您也不能使 useEffect
回调成为 async
函数,因为它不能 return Promise。所以我们坚持使用 setState
.
另请注意,确实没有理由直接调用 client.query
,特别是因为如果缓存发生变化,此代码 不会 重新呈现您的 UI .您应该使用 useQuery
和钩子已经为您公开的 data
状态。
我试图在顶层捕获一些错误,以展示世界上最漂亮的错误页面。
出于某种原因,我看到我的节点已断开连接,但错误边界从未触发。
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: any) {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Had error</h1>
} else {
return this.props.children;
}
}
}
function App() {
const [data, setData] = useState<any>(null);
useEffect(() => {
client.query({ query })
.then(res => setData(res))
.catch(err => { console.warn("Error:", err); throw err; });
}, []);
return <pre>Data: {data}</pre>;
}
ReactDOM.render(
<ErrorBoundary>
<App />
</ErrorBoundary>,
document.getElementById('root')
);
我 运行 这是在一个空的 create-react-app 项目中。
我希望看到<h1>Had error</h1>
;我收到 CRA 未处理的错误屏幕。
来自docs
Error boundaries do not catch errors for:
- Event handlers (learn more)
- Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
- Server side rendering
- Errors thrown in the error boundary itself (rather than its children)
Promise 是异步的,因此被拒绝的 Promises 不会被错误边界捕获。目前,recommended but somewhat hackish approach 是在setState
中抛出错误。在功能组件中,您可以使用由 useState
钩子编辑的设置函数 return 代替 setState
:
const [, setState] = useState()
useEffect(() => {
client.query({ query })
.then(res => setData(res))
.catch(err => {
console.warn("Error:", err);
setState(() => {
throw err;
});
});
}, []);
在 useEffect
中抛出也可以,但在 Promise 的 then
或 catch
回调中不行。您也不能使 useEffect
回调成为 async
函数,因为它不能 return Promise。所以我们坚持使用 setState
.
另请注意,确实没有理由直接调用 client.query
,特别是因为如果缓存发生变化,此代码 不会 重新呈现您的 UI .您应该使用 useQuery
和钩子已经为您公开的 data
状态。