也可以这么写
但是,如果用try…catch…捕获的error,无法被window.onerror捕获
没有return false ,window.onerror也没有执行,errorHandler已经是全局的监听
window.onerror与errorHandler互斥
只有window.onerror监听到了错误
监听所有下级组件报错,可降级展示UI(显示 出错啦~~ 友好提示)
只监听组件渲染时的报错,不监听DOM事件、异步错误(可用try-catch、window.onerror)
只在production生产环境生效,测试环境直接抛出错误
src/ErrorBoundary.tsx
import React from 'react'
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = {
error: null // 存储当前报错信息
}
}
static getDerivedStateFromError(error) {
// 更新state 时下一次渲染能够显示降级后的UI
console.log('getDerivedStateFromError...', error)
return { error }
}
componentDidCatch(error, errorInfo) {
console.info('componentDidCatch...', error, errorInfo)
}
render() {
if (this.state.error) {
// 提示错误
return <h1>报错了</h1>
}
// 没有错误 正常渲染
return this.props.children
}
}
export default ErrorBoundary
index.tsx
ClassDemo.tsx
import React from 'react'
class ErrorDemo extends React.Component {
constructor(props:any) {
super(props)
this.state = {
num: 100
}
}
clickHandler = () => {
// this.state.num() // ErrorBoundary 无法监听DOM事件报错,需要自行 try-catch、window.onerror
}
componentDidMount() {
// throw new Error('mounted error') // ErrorBoundary 可监听渲染过程的报错
// setTimeout(() => { // 无法监听异步报错,会直接抛出
// throw new Error('setTimeout error')
// }, 1000)
}
render() {
return <div>
<p>error demo - class</p>
<button onClick={this.clickHandler}>error</button>
</div>
}
}
export default ErrorDemo
FunctionDemo.tsx
import { useState, useEffect } from 'react'
function ErrorDemo() {
const [num] = useState(100)
function clickHandler() {
// num() // ErrorBoundary 无法监听事件报错,需要自行 try-catch
}
// useEffect(() => {
// throw new Error('mounted error') // ErrorBoundary 可监听渲染过程的报错
// }, [])
return <div>
<p>error demo - functional</p>
<button onClick={clickHandler}>error</button>
</div>
}
export default ErrorDemo