动态加载
Suspense 配合 React.lazy 可以实现动态加载功能
// React.lazy 接受一个函数,这个函数需要动态调用 `import()`。
// 它必须返回一个 Promise ,该 Promise 需要 resolve 一个 default export 的 React 组件。
const ChannelHome = React.lazy(
() => import(/* webpackChunkName: 'ChannelHome'*/ "./ChannelHome")
);
const ChannelList = React.lazy(
() => import(/* webpackChunkName: 'ChannelList'*/ "./ChannelList")
);
function Routes() {
return (
<Router>
<React.Suspense fallback={<div>loading...</div>}>
<Switch>
<Route path="/index" component={ChannelHome} />
<Route path="/list" component={ChannelList} />
<Redirect from={"/*"} to={"/index"} />
</Switch>
</React.Suspense>
</Router>
);
}
Suspense 原理
Suspense 在执行内部可以通过 try{}catch{} 方式捕获异常,这个异常通常是一个 Promise ,可以在这个 Promise 中进行数据请求工作,Suspense 内部会处理这个 Promise ,Promise 结束后,Suspense 会再一次重新 render 把数据渲染出来,达到异步渲染的效果。
渲染错误边界
为了避免某一组件渲染出错导致页面白屏,React提供componentDidCatch 和 static getDerivedStateFromError() 两个额外的生命周期,去挽救由于渲染阶段出现问题造成 UI 界面无法显示的情况。
componentDidCatch
componentDidCatch 可以捕获异常,它接受两个参数:
- 1 error —— 抛出的错误。
- 2 info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。
componentDidCatch 作用:
- 可以调用 setState 促使组件渲染,并做一些错误拦截功能。
- 监控组件,发生错误,上报错误日志。
static getDerivedStateFromError
getDerivedStateFromError 返回的值可以合并到 state,作为渲染使用。由于是静态方法,所以不能使用setState。
注意事项: 如果存在 getDerivedStateFromError 生命周期钩子,那么将不需要 componentDidCatch 生命周期再降级 ui。
官方推荐使用getDerivedStateFromError这个方法。
具体实例如下:
<ErrorBoundary>
<Home />
</ErrorBoundary>
// ErrorBoundary
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能够显示降级后的 UI
console.log('---错误边界捕获到错误---', error)
return { hasError: true }
}
componentDidCatch(error, errorInfo) {
// 你同样可以将错误日志上报给服务器
console.log('---错误边界捕获到错误---', error, errorInfo)
}
render() {
if (this.state.hasError) {
return (
<div>页面发生异常</div>
)
}
return this.props.children
}
}
export default ErrorBoundary