这是我一直在寻找的答案:
fetcher.js
export async function fetcher(url) {
const rsp = await fetch(url);
if (rsp.ok) {
return await rsp.json();
} else {
const MyError = function (message, status) {
this.message = `${message} from url ${url} status code:${status}`;
this.status = status;
};
throw new MyError(rsp.statusText, rsp.status);
}
}
错误边界.js
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true, message: error?.message, status: error?.status };
}
render() {
function addExtraProps(Component, extraProps) {
return <Component.type {...Component.props} {...extraProps} />;
}
if (this.state.hasError) {
return addExtraProps(this.props.fallback, {
errorMessage: this.state.message,
errorStatus: this.state.status,
});
}
return this.props.children;
}
}
然后用法是这样的:
function CityLayout(props) {
const { setSelectedCityId } = useContext(CityContext);
return (
<>
<CityListMaxDDL />
<CityList displayCount={5} />
<CityDetail cityId={setSelectedCityId} />
</>
);
}
function App() {
function MyErrorBoundaryFallback({ errorMessage, errorStatus }) {
return (
<div className="container">
<h1>Error</h1>
<div className="row">
Error Status: <b>{errorStatus}</b>
</div>
<div className="row">
ErrorMessage: <b>{errorMessage}</b>
</div>
</div>
);
}
return (
<ErrorBoundary fallback={<MyErrorBoundaryFallback />}>
<Suspense fallback={<div>Loading..</div>}>
<div className="container">
<CityProvider>
<CityLayout />
</CityProvider>
</div>
</Suspense>
</ErrorBoundary>
);