React 异常处理
目录
1. Error Boundaries 组件
官方文档: Only class components can be error boundaries.
在没有 Error Boundaries 之前, 如果某个组件扔出了错误, 则整个项目都会被影响.
但 Error Boundary 只有其子组件(child component tree)才会 catch 到异常, 而不会影响到其它组件的渲染.
例如下面在App
组件中渲染的Live2DWidget
组件(一个看板娘), 如果Live2DWidget
由于某些原因出现异常, 我们更希望保持其他的 UI 例如<Navbar />
而不是整个页面白掉.
import React, { useState, useEffect, Component } from "react"
// 看板娘组件
const Live2DWidget = () => {
const [status, setStatus] = useState("NORMAL")
// 当status 不为NORMAL状态时 扔出异常
if (status !== "NORMAL") {
throw new Error("Error: 看板娘错误")
}
return (
<>
<h1> (。・∀・)ノ゙嗨</h1>
<button onClick={() => setStatus("OFFLINE")}>点我</button> {/* 测试点击用 */}
</>
)
}
// 边界错误组件 可以用props来传递渲染的组件
class ErrorBoundary extends Component {
constructor(props) {
super(props)
this.state = {
error: null,
errorInfo: null,
}
}
componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo,
})
}
render() {
// 返回的UI
if (this.state.errorInfo) {
return this.props.display // 渲染异常展示组件
}
return this.props.children // 无异常则渲染原组件
}
}
// 错误面板组件.
const ErrorModal = props => {
return (
<>
<h1>{props.message}</h1>
<button>关闭</button>
</>
)
}
const App = () => {
return (
<>
<h1>Welcome back!</h1>
<ErrorBoundary display={<ErrorModal message="看板娘错误" />}>
<Live2DWidget />
</ErrorBoundary>
</>
)
}
export default App
总结
ErrorBoundary
必须是 class-components- 如果异常则返回 fallback 的 UI
- ErrorBoundary 只是负责 catch 且逻辑相同, 因此可以用 props 来传递 fallback 的 UI 而不是创建多个不同的 Error Boundary 组件
- 异常只针对 child component tree, 对其他 UI 没影响
2. Event Handler
事件异常则可直接用try / catch
处理.
const App = () => {
const [error, setError] = useState(false)
const handleEditProfile = () => {
try {
// POST
} catch (err) {
setError(err)
console.log(err)
}
}
return (
<>
{error && <ErrorModal />}
<h1>User info</h1>
<button onClick={handleEditProfile}>Edit Profile</button>
</>
)
}