mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-25 18:50:56 +02:00
UI: Improve Recovery Mode screen (#2206)
This commit is contained in:
+20
-18
@@ -1,8 +1,8 @@
|
||||
import React, { ErrorInfo } from "react";
|
||||
import React, { type ErrorInfo } from "react";
|
||||
|
||||
import { IErrorData, getErrorForDisplay } from "../utils/ErrorHelper";
|
||||
import { type CrashReport, getCrashReport } from "../utils/ErrorHelper";
|
||||
import { RecoveryRoot } from "./React/RecoveryRoot";
|
||||
import { Page } from "./Router";
|
||||
import type { Page } from "./Router";
|
||||
import { Router } from "./GameRoot";
|
||||
|
||||
type ErrorBoundaryProps = {
|
||||
@@ -12,7 +12,7 @@ type ErrorBoundaryProps = {
|
||||
|
||||
type ErrorBoundaryState = {
|
||||
error?: Error;
|
||||
errorInfo?: React.ErrorInfo;
|
||||
reactErrorInfo?: ErrorInfo;
|
||||
page?: Page;
|
||||
hasError: boolean;
|
||||
};
|
||||
@@ -27,40 +27,42 @@ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoun
|
||||
this.setState({ hasError: false });
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
componentDidCatch(error: Error, reactErrorInfo: ErrorInfo): void {
|
||||
this.setState({
|
||||
errorInfo,
|
||||
reactErrorInfo: reactErrorInfo,
|
||||
page: Router.page(),
|
||||
});
|
||||
console.error(error, errorInfo);
|
||||
console.error(error, reactErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* When an error is thrown, this function is called twice and renders RecoveryRoot with two different errorData, even
|
||||
* when there is only one error. The flow is roughly like this:
|
||||
* When an error is thrown, this function is called twice and renders RecoveryRoot with two different crashReport,
|
||||
* even when there is only one error. The flow is roughly like this:
|
||||
* - The error is thrown.
|
||||
* - getDerivedStateFromError() -> Set hasError and error
|
||||
* - render() -> Render RecoveryRoot with errorData1, which does not contain errorInfo and page
|
||||
* - componentDidCatch() -> Set errorInfo and page
|
||||
* - render() -> Render RecoveryRoot with errorData2, which contains errorInfo and page
|
||||
* - render() -> Render RecoveryRoot with crashReport1, which does not contain reactErrorInfo and page
|
||||
* - componentDidCatch() -> Set reactErrorInfo and page
|
||||
* - render() -> Render RecoveryRoot with crashReport2, which contains reactErrorInfo and page
|
||||
*
|
||||
* This means that if we use useEffect(()=>{}, [errorData]) in RecoveryRoot, that hook will be called twice with 2
|
||||
* different errorData. The second errorData, which contains errorInfo and page, is the "final" value that is shown on
|
||||
* the recovery screen.
|
||||
* This means that if we use useEffect(()=>{}, [crashReport]) in RecoveryRoot, that hook will be called twice with 2
|
||||
* different crashReport. The second crashReport, which contains reactErrorInfo and page, is the "final" value that is
|
||||
* shown on the recovery screen.
|
||||
*/
|
||||
render(): React.ReactNode {
|
||||
if (this.state.hasError) {
|
||||
let errorData: IErrorData | undefined;
|
||||
let crashReport: CrashReport | undefined;
|
||||
if (this.state.error) {
|
||||
try {
|
||||
// We don't want recursive errors, so in case this fails, it's in a try catch.
|
||||
errorData = getErrorForDisplay(this.state.error, this.state.errorInfo, this.state.page);
|
||||
crashReport = getCrashReport(this.state.error, this.state.reactErrorInfo, this.state.page);
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return <RecoveryRoot softReset={this.props.softReset} errorData={errorData} resetError={() => this.reset()} />;
|
||||
return (
|
||||
<RecoveryRoot softReset={this.props.softReset} crashReport={crashReport} resetError={() => this.reset()} />
|
||||
);
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user