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

MySQL 8.0.21 installation and configuration method graphic tutorial

Record the installation and configuration method ...

How to use a field in one table to update a field in another table in MySQL

1. Modify 1 column update student s, city c set s...

Analysis of the principle and creation method of Mysql temporary table

This article mainly introduces the principle and ...

Analysis of the advantages and disadvantages of MySQL stored procedures

MySQL version 5.0 began to support stored procedu...

Deploy Varnish cache proxy server based on Centos7

1. Varnish Overview 1. Introduction to Varnish Va...

How to configure Linux firewall and open ports 80 and 3306

Port 80 is also configured. First enter the firew...

Implementation of Docker cross-host network (manual)

1. Introduction to Macvlan Before the emergence o...

Detailed explanation of LVM seamless disk horizontal expansion based on Linux

environment name property CPU x5650 Memory 4G dis...

Abbreviation of HTML DOCTYPE

If your DOCTYPE is as follows: Copy code The code ...

36 principles of MySQL database development (summary)

Preface These principles are summarized from actu...

nginx solves the problem of slow image display and incomplete download

Written in front Recently, a reader told me that ...

CSS3 creates 3D cube loading effects

Brief Description This is a CSS3 cool 3D cube pre...