PrefaceStarting from React 16, the concept of Error Boundaries was introduced, which can capture errors generated in its child components, record error logs, and display downgrade content. The specific official website address Error boundaries prevent a component error from causing the entire page to become unusable with a blank screen. They use graceful degradation to present an alternative UI. Error boundaries can capture errors during rendering, in the lifecycle, and in the constructor of the entire component tree. Since React 16, any error not caught by an error boundary will cause the entire React component tree to be unmounted. ErrorBoundary meaning
When browsing a page, the user experience may be poor due to exceptions returned by the backend or some error checks in the front end. Just imagine that you are sitting on a train with your wife, eating hot pot and singing songs, How to implement the official website👉 If a class component defines any (or both) of the two lifecycle methods static getDerivedStateFromError() or componentDidCatch(), it becomes an error boundary. When an error is thrown, use static getDerivedStateFromError() to render the alternate UI and componentDidCatch() to print the error message 👈 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so that the next rendering can display the degraded UI return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can also report error logs to the server logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // You can customize the downgraded UI and render return <h1>Something went wrong.</h1>; } return this.props.children; } } Then you can use it as a regular component: <ErrorBoundary> <MyWidget /> </ErrorBoundary> Error boundaries work similarly Encapsulates a configurable ErrorBoundary After understanding how the official website implements the error boundary component, we can encapsulate an 1. Create a configurable ErrorBoundary class component Compared with
class ErrorBoundary extends React.Component { state = { error: false }; static getDerivedStateFromError(error) { return { error }; } componentDidCatch(error, errorInfo) { if (this.props.onError) { //The report log is executed through the function injected by the parent component this.props.onError(error, errorInfo.componentStack); } } render() { const { fallback, FallbackComponent } = this.props; const { error } = this.state; if (error) { const fallbackProps = { error }; //Determine whether it is a React Element if (React.isValidElement(fallback)) { return fallback; } //Component method if (FallbackComponent) { return <FallbackComponent {...fallbackProps} />; } throw new Error("ErrorBoundary component needs to be passed into the fallback UI"); } return this.props.children; } } In this way, the underlying 1. Add a method in ErrorBoundary to detect whether there is an injected reset method. If there is a reset method, execute it and reset the error in state to make its error state falseresetErrorBoundary = () => { if (this.props.onReset) this.props.onReset(); this.setState({ error: false }); }; 2. Add a function component type in render for rendering. The reset method and error information can be passed as parameters to the current component for processing.render() { const { fallback, FallbackComponent, fallbackRender } = this.props; const { error } = this.state; if (error) { const fallbackProps = { error, resetErrorBoundary: this.resetErrorBoundary, }; ... if (typeof fallbackRender === "function")return fallbackRender(fallbackProps); ... } return this.props.children; } 2. Wrap ErrorBoundary with a high-order function and return itimport React from "react"; import DefaultErrorBoundary from "./core"; const catchreacterror = (Boundary = DefaultErrorBoundary) => InnerComponent => { return props => ( <Boundary {...props}> <InnerComponent {...props} /> </Boundary> ); }; Usage & TestingThrough a click-to-increment demo, when the number reaches a certain value, an exception is thrown. Here, the class component and the Function component are tested as the components that initiate the exception.
//Function component const fnCount1 = ({ count }) => { if (count == 3) throw new Error("count is three"); return <span>{count}</span>; }; //Class component class fnCount2 extends React.Component { render() { const { count } = this.props; if (count == 2) throw new Error("count is two"); return <span>{count}</span>; } }
const errorbackfn = ({ error: { message }, resetErrorBoundary }) => ( <div> <p>Something went wrong</p> <pre>{message}</pre> <button onClick={resetErrorBoundary}>Try again</button> </div> );
const errorbackcom = () => <h1>An error has occurred and cannot be undone</h1>;
//Wrap the component that initiated the exception and return a high-order component that can handle error editing const SafeCount1 = catchreacterror()(fnCount1); const SafeCount2 = catchreacterror()(fnCount2); //Test main component const App = () => { const [count, setCount] = useState(0); const ListenError = (arg, info) => console.log("Error: " + arg.message, info); //Callback when error occurs const onReset = () => setCount(0); //Callback when reset is clicked return ( <div className="App"> <section> <button onClick={() => setCount(count => count + 1)}>+</button> <button onClick={() => setCount(count => count - 1)}>-</button> </section> <hr /> <div> Class component: <SafeCount2 count={count} fallbackRender={errorbackfn} onReset={onReset} onError={ListenError} /> </div> <div> Function component: <SafeCount1 count={count} FallbackComponent={errorbackcom} onError={ListenError} /> </div> </div> ); }; Mission accomplished! Problems encountered & summaryThere are many times when react error boundaries are not omnipotent, such as
In the above example, this.o does not exist, so an error will be reported. Window.onerror can capture it, but the error boundary cannot.
Server-side rendering and error boundaries themselves Summarize
So far, thank you for taking the time to read this article. I hope it can be helpful to you. I believe that you have a general understanding of the error boundaries in react and can write a simple You may also be interested in:
|
<<: MySQL 8.0.3 RC is about to be released. Let’s take a look at the changes
>>: How to query and update the same table in MySQL database at the same time
The company's business scenario requires the ...
win10 + Ubuntu 20.04 LTS dual system installation...
Preface I have an old laptop with Win7. In order ...
1. Concat function. Commonly used connection stri...
This time, we will try to package the running con...
This article mainly introduces the ::master pseud...
Without further ado, here is a demo picture. The ...
The requirement is to pass in the rating data for...
Table of contents Preface Problem Description Cau...
Physically speaking, an InnoDB table consists of ...
Table of contents Overview Getting started with d...
Table of contents 1. Demand 2. Implementation 3. ...
Table of contents Understand the core concept of ...
From handicraft design to graphic design to web de...
<br />Related articles: 9 practical suggesti...