1. 程式人生 > 程式設計 >React中Portals與錯誤邊界處理實現

React中Portals與錯誤邊界處理實現

目錄
  • Portals
  • 錯誤邊界處理
  • 如果沒有使用錯誤邊界會怎樣?
  • 注意點

Portals

可以說是 插槽,但 不同於 中的 slot,它指的是將一個 React 元素渲染到指定的容器 (真實 DOM) 中

比如說,Modal 元件一般預設直接作為 body 的真實結構的子元素渲染出來,那麼我們就可以藉助 ReactDOM.createPortal(ReactElement,RealDOM container) 建立一個 React 元素,示例程式碼:

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 />
    </d
iv> }

我們可以在瀏覽器控制檯中看到,真實的 Modal 元件其實是作為 body 的直接子元素渲染出來的,但通過 React 開發者工具,我們可以看到 Modal 元件在虛擬 DOM 樹的結構中依舊在 App 元件下,類名為 app-container 的 div 中

所以,我們可以得出結論:React 元件虛擬 DOM 樹結構與真實 DOM 樹結構可以是不一致的

因而需要注意事件冒泡

  • React 中的事件其實是經過包裝的
  • 它的事件冒泡是根據虛擬 DOM 樹的結構來冒泡的,而不是真實 DOM 樹的冒泡機制

錯誤邊界處理

預設情況下,若一個元件在渲染期間 (render) 發生錯誤,那麼就會導致整個元件樹全部被解除安裝

錯誤邊界:就是一個元件,用於捕獲 渲染期間 子元件發生的錯誤,並有能力阻止錯誤繼續向父元件傳播

讓某個元件捕獲錯誤 (類元件):

使用靜態方法 static getDerivedStateFromError,子元件渲染錯誤時會觸發此函式

  • 靜態方法,所以不能使用 this
  • 此函式返回值 (物件) 會與 state 混合覆蓋狀態
  • 觸發時間點為:渲染子元件發生錯誤後,在更新頁面之前
  • 只有子元件渲染髮生錯誤,才會觸發 (即自身元件發生錯誤或其兄弟元件、父元件發生錯誤均不會觸發)
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
    }
}

使用 componentDidCatch(error,info) 函式

  • 是個例項方法
  • 執行時機在渲染子HGFbeOwyI元件發生錯誤後,且頁面更新之後 (更改狀態會導致元件樹解除安裝完之後又重新構建元件樹,比較浪費效率)
  • 通常該函式用於往後臺傳遞並記錄錯誤資訊
import React,{PureComponent} from 'react'

export default class ErrorBoundary extends PureComponent {
    state = {
        isError: false
    }
    componentDidCatch(error,info) {
        // inf客棧o 即為錯誤的摘要資訊
        console.log('Rendering Error: ',error)
        console.log('Rendering info: ',info)
        this.setState({
            isError: true
        })
    }
    rendewww.cppcns.comr() {
        if (this.isError) {
            return <span>Something Wrong...</span>
        }
        return this.props.children
    }
}

如果沒有使用錯誤邊界會怎樣?

自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導致整個 React 元件樹被解除安裝。

經驗告訴我們,完全移除比保留錯誤UI更好。例如,在類似 Messenger 的產品中,把異常的 UI 展示給使用者可能會導致使用者將資訊錯發給別人。

增加錯誤邊界能夠讓你在應用發生異常時提供更好的使用者體驗。例如,Facebook Messenger 將側邊欄、資訊面板、聊天記錄以及資訊輸入框包裝在單獨的錯誤邊界中。如果其中的某些 UI 元件崩潰,其餘部分仍然能夠互動。

注意點

某些錯誤,錯誤邊界元件不會捕獲

自身元件的錯誤

非同步的錯誤 (如 setTimeout 中丟擲的錯誤)

import React,{PureComponent} from 'react'

// ErrorBoundary.x
export default class ErHGFbeOwyIrorBoundary 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
    }
}

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

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

事件中丟擲的錯誤

即:僅處理渲染子元件期間的同步錯誤

到此這篇關於React中Portals與錯誤邊界處理實現的文章就介紹到這了,更多相關React Portals與錯誤邊界處理內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!