设计动机
白屏场景:
- 前端边缘场景导致的代码错误
- 沟通没有对称,后端数据结构的突变导致代码层报错
- 后端部署服务导致的接口不可用进而产生的前端报错
解决方案:
为了提升用户体验上的友好,增加ErrorBoundary
做UI层
降级当页面发生报错的时候,用户依然可以点击菜单栏进行模块切换,无需刷新页面或者重新打开路由,防止客户暴躁的情况出现
具体实现:
- 增加
ErrorBoundary
组件,用于捕获错误,将其包裹在渲染非导航栏渲染位置
- 记录报错路由,当用户重新点击其他模块时与错误路由比较,如果不一致,取消错误,重新请求页面
- 渲染遇到错误时对应需要展示的组件
ErrorBoundary
ErrorBoundary.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, pathname: props.location.pathname }; } static getDerivedStateFromError() { return { hasError: true }; } componentDidUpdate(nextProps, nextState) { if (nextProps.history.location.pathname !== nextState.pathname && this.state.hasError) { this.setState({ hasError: false, }); } } componentDidCatch(error) { this.setState({ pathname: this.props.location.pathname, }); console.log(error); } render() { if (this.state.hasError) { return <ErrorUI />; } return this.props.children; } }
export default withRouter(ErrorBoundary);
|
注意点:
componentDidUpdate
中获取最新路由的时候需要从nextProps
中路由对象history
中获取,而非location
,location
获取到的并非最新的路由,而且跳转前当前的路由
componentDidCatch
用户捕获错误,方法可以返回error
,可以在其进行错误上报,未来可扩展
Layout.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <Layout> <Navigation collapsed={collapsed} customExtraItem={customExtraItem} customNavigation={customNavigation} logo={logo} pathArr={pathArr} toggleCollapsed={toggleCollapsed} {...navigation} /> <Layout className={styles['section']}> { !noSider && <SideMenu collapsed={collapsed} customSideMenu={customSideMenu} customSideMenuItem={customSideMenuItem} getBadgeCount={getBadgeCount} keyMap={keyMap} menu={menu} pathArr={pathArr} toggleCollapsed={toggleCollapsed} /> } <div className={styles['content']}> <ErrorBoundary> {children} </ErrorBoundary> </div> </Layout> </Layout>
|
效果展示