Implementation of Portals and Error Boundary Handling in React

Implementation of Portals and Error Boundary Handling in React

Portals

It can be said to be a slot, but different from the slot in Vue, it refers to rendering a React element into a specified container (real DOM)

For example, the Modal component is usually rendered directly as a child element of the real structure of the body by default, so we can use ReactDOM.createPortal(ReactElement, RealDOM container) to create a React element, example code:

import React from 'react'
import ReactDOM from 'react-dom'
import Modal from './components/Modal'

const PortalModal = ReactDOM.createPortal(<Modal />, document.body)

export default function App() {
    return <div className="app-container">
        <PortalModal />
    </div>
}

We can see in the browser console that the real Modal component is actually rendered as a direct child element of the body, but through the React developer tools, we can see that the Modal component is still under the App component in the virtual DOM tree structure, in the div with the class name app-container

Therefore, we can conclude that the React component virtual DOM tree structure may be inconsistent with the real DOM tree structure.

Therefore, we need to pay attention to event bubbling

  • Events in React are actually packaged
  • Its event bubbling is based on the structure of the virtual DOM tree, not the bubbling mechanism of the real DOM tree.

Error Boundary Handling

By default, if a component has an error during rendering, the entire component tree will be unmounted. Error boundary: A component that captures errors that occur in child components during rendering and has the ability to prevent errors from propagating to parent components.

Let a component catch errors (class component):

Use the static method static getDerivedStateFromError, which will be triggered when a subcomponent renders an error

  • Static method, so this cannot be used
  • The return value (object) of this function will be mixed with state to cover the state
  • The triggering time is: after an error occurs in rendering a subcomponent and before updating the page
  • It will only be triggered if an error occurs in the rendering of a child component (that is, it will not be triggered if an error occurs in its own component or its sibling components or parent components)
import React, {PureComponent} from 'react'

export default class ErrorBoundary extends PureComponent {
    state = {
        isError: false
    }
    static getDerivedStateFromError(error) {
        console.log('Rendering Error: ', error)
        return {
            isError: true
        }
    }
    render() {
        if (this.isError) {
            return <span>Something Wrong...</span>
        }
        return this.props.children
    }
}

Using componentDidCatch(error, info) function

  • It is an instance method
  • The runtime is after an error occurs in rendering a subcomponent and after the page is updated (changing the state will cause the component tree to be rebuilt after it is uninstalled, which is a waste of efficiency)
  • Usually this function is used to pass and record error information to the background
import React, {PureComponent} from 'react'

export default class ErrorBoundary extends PureComponent {
    state = {
        isError: false
    }
    componentDidCatch(error, info) {
        // info is the error summary console.log('Rendering Error: ', error)
        console.log('Rendering info: ', info)
        this.setState({
            isError: true
        })
    }
    render() {
        if (this.isError) {
            return <span>Something Wrong...</span>
        }
        return this.props.children
    }
}

What happens if error boundaries are not used?

Starting from React 16, any error not caught by an error boundary will cause the entire React component tree to be unmounted.

Experience has shown us that it is better to remove the buggy UI completely than to keep it around. For example, in a product like Messenger, presenting an unusual UI to the user may cause the user to send the wrong message to someone else.

Adding error boundaries allows you to provide a better user experience when exceptions occur in your application. For example, Facebook Messenger wraps the sidebar, message panel, chat history, and message input box in separate error boundaries. If some of the UI components crash, the rest will still be interactive.

Note

Some errors are not caught by the error boundary component

Errors in own components

Asynchronous errors (such as errors thrown in setTimeout)

import React, {PureComponent} from 'react'

// ErrorBoundary.jsx
export default class ErrorBoundary extends PureComponent {
    state = {
        isError: false
    }
    /* This function will not run */
    static getDerivedStateFromError(error) {
        console.log('Rendering Error: ', error)
        return {
            isError: true
        }
    }
    render() {
        if (this.isError) {
            return <span>Something Wrong...</span>
        }
        return this.props.children
    }
}

// Comp.jsx Comp component export default function Comp() {
    setTimeout(() => {
        throw new Error('setTimeout error')
    }, 1000)
    return <div>Comp</div>
}

// App.jsx uses export default function App() {
    return <>
        <ErrorBoundary>
            <Comp />
        </ErrorBoundary>
    </>
}

Errors thrown in events

That is: only handle synchronous errors during rendering of child components

This is the end of this article about the implementation of Portals and error boundary handling in React. For more relevant React Portals and error boundary handling content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Encapsulate a simplest ErrorBoundary component to handle react exceptions
  • React error boundary component processing
  • Detailed explanation of exception handling in React 16
  • React workflow and Error Boundaries implementation process explanation

<<:  Detailed explanation of the complete usage example of developing hyperf under Docker

>>:  Detailed explanation on reasonable settings of MySQL sql_mode

Recommend

Detailed analysis and usage of tcpdump command under Linux

Introduction To put it simply, tcpdump is a packe...

Linux kernel device driver kernel linked list usage notes

/******************** * Application of linked lis...

How to analyze SQL execution plan in MySQL through EXPLAIN

Preface In MySQL, we can use the EXPLAIN command ...

Detailed explanation of Vue form binding and components

Table of contents 1. What is two-way data binding...

MYSQL uses Union to merge the data of two tables and display them

Using the UNION Operator union : Used to connect ...

Detailed explanation of the life cycle of Angular components (Part 2)

Table of contents 1. View hook 1. Things to note ...

A brief analysis of the basic concepts of HTML web pages

What is a web page? The page displayed after the ...

Example of using Docker Swarm to build a distributed crawler cluster

During the crawler development process, you must ...

How to elegantly back up MySQL account information

Preface: I recently encountered the problem of in...

The shortest JS to determine whether it is IE6 (IE writing method)

Commonly used JavaScript code to detect which ver...

How to hide and forge version number in Nginx

1. Use curl command to access by default: # curl ...

Native js to implement form validation function

Table of contents When developing, analyzing the ...

14 Ways to Create Website Content That Engages Your Visitors

When I surf the Net, I often see web sites filled...