---
group:
  title: 项目开发规范
title: 9.页面错误显示
---

## 页面错误显示（交互）

1. `src/app.tsx`上配置关闭antdPro自带的错误边界处理功能 `ErrorBoundary: false`
2. `src/layouts/index.tsx`上加上自定义"错误边界处理组件( `pages/Error/ErrorBoundary/index.tsx`)"，显示"刷新页面"及"返回首页"按钮。
3. 针对找不到页面文件则自动刷新当前页（出现情况：用户在页面上停留太久未操作且nginx已经更新新代码的情况下）
    - 方式一：直接在"错误边界处理组件"内判断错误类型是否是`ChunkLoadError`来刷新当前页面。如果执行一次自动刷新还未找着页面文件则跳转到首页，但是若是首页错误，则不再进行跳转）
    - 方式二：在`src/global.tsx`内加上错误监听（无法判断找不到页面的错误类型，暂时不应用，后续有其他方面的错误可考虑在此处处理）
    

### 错误边界组件代码
`pages/Error/Error/ErrorBoundary/index.tsx`
``` 
/* eslint-disable */
import React from 'react'
import { Button, Result } from "antd";
import { getCurrentLocationPath } from "@/utils/publicBusiness";
// 错误边界组件，参考：https://www.5axxw.com/questions/simple/ifz84c
// @ts-ignore
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
// @ts-ignore
    this.state = {
      hasError: false,
      errorMessage: ''
    };
  }

  static getDerivedStateFromError(error) {
    // console.log('getDerivedStateFromError=>error', error)
    // console.log('getDerivedStateFromError=>error.message', error.message);
    // console.log('getDerivedStateFromError=>error.name', error.name, error.name === 'ChunkLoadError');
    if (error.name === 'ChunkLoadError') {
      // console.log('找不到页面的错误，交互方式：刷新页面')
      const hasDoneReload = window.sessionStorage.getItem(`${process.env.siteName}-ChunkLoadErrorRefresh`)
      if (hasDoneReload && hasDoneReload === window.location.pathname) {
        // 判断当前页面是否已经刷新过，如果已经刷新过，则跳转到首页去（解决重复刷新的问题，但需要排除首页）
        const ignorePaths = ['/', '/projectView/singleProject']
        const newPathname = getCurrentLocationPath('/' + process.env.baseBuildPath);
        if (ignorePaths.includes(newPathname)) {
          // 如果是首页，则不做处理，让用户自行操作
        } else {
          // 跳转到首页
          window.location.href = `/${process.env.baseBuildPath ? process.env.baseBuildPath + '/' : ''}`
        }
        // 并清空存储记录
        window.sessionStorage.removeItem(`${process.env.siteName}-ChunkLoadErrorRefresh`)
      } else {
        window.sessionStorage.setItem(`${process.env.siteName}-ChunkLoadErrorRefresh`, window.location.pathname)
        window.location.reload()
      }
    }
    // console.log('报错是提示语', error?.message)
    // Update state so the next render will show the fallback UI.
    return { hasError: true, errorMessage: error?.message, errorPathname: window.location.href };
  }

  componentDidCatch(error, info) {
    // 将错误信息打印到控制台
    // console.error("Error caught by error boundary:", error);
    // 更新组件状态
    // this.setState({ hasError: true, errorMessage: JSON.stringify(error) });
  }

  handlePageJump = (key) => {
    if (key === 'refresh') {
      window.location.reload()
    }
    if (key === 'home') {
      window.location.href = `/${process.env.baseBuildPath ? process.env.baseBuildPath + '/' : ''}`
    }
  }

  render() {
    if (this.state.hasError) {
      return <Result status={'error'} title={'糟糕，页面出了错误!'}
                     subTitle={this.state.errorMessage}
                     extra={[
                       <Button type="primary" key="refresh" onClick={() => this.handlePageJump('refresh')}>刷新页面</Button>,
                       <Button key="home" onClick={() => this.handlePageJump('home')}>返回首页</Button>,
                     ]}
      >

      </Result>
    }
    return this.props.children;
  }
}

export default ErrorBoundary
```

项目工具类： getCurrentLocationPath()
```
// 判断当前URL是不是有带指定 目录，如果有将其替换
const getCurrentLocationPath = (contentPath: string) => {
  const { pathname } = window.location;
  let newPathname = pathname;
  // 部署到非根路径，需要对应的把前缀目录去除
  if (contentPath && contentPath !== '/' && pathname.indexOf(contentPath) !== -1) {
    newPathname = pathname.replace(contentPath, '');
  }
  return newPathname;
};

```
### 监听页面错误
`src/global.tsx`
```
// 监听错误处理
window.onerror = function (message, source, lineno, colno, error) {
  // message：错误信息，如“Uncaught SyntaxError: Invalid or unexpected token”
  // source：发生错误的脚本URL
  // lineno：发生错误的行号
  // colno：发生错误的列号
  // error：错误对象，包含更多详细信息

  // 可以在这里添加处理错误的逻辑，例如发送错误报告到服务器
  console.log("Error: " + message);
  console.log("Source: " + source);
  console.log("Line: " + lineno);
  console.log("Column: " + colno);
  console.log("Error object: " + JSON.stringify(error));
  if (error) {
    console.log('在此可做错误处理', error)
    console.log('报错类型/名称=>name', error.name)
    console.log('报错提示信息=>message', error.message)
  }
  // 返回true可以阻止错误被浏览器默认处理
  return true;
};
```