开发者问题收集

React:使用 React Router 重定向到带有错误消息/堆栈跟踪的错误页面

2021-04-29
13398

在我的应用中,如果组件内部发生任何错误,我需要重定向到顶级错误页面。假设我使用 React-Router 并定义了以下路由,

<Switch>
   ..
   <Route path="/error">
      <Error />
   </Route>

假设在某些下级组件中出现故障。我得到一个带有 .message.stackerror 对象。我需要我的 Error 组件在 Router <Redirect /> 之后显示错误详细信息。

const [error, setError] = useState({});

const someComponentFetch = async () => {
    const url = '/myapp/data';
    try {
         //...
    }
    catch (error) { 
        setError(error);
    }
}  

if (error.message) {
    return <Redirect to="/error" />
}

return (..);

Error 组件需要一个 props 对象:

export default function Error(props) {
    return (
        <div>
            Error Occurred: 
            <div>
                Message: {props.error.message} <br/>
                Stack: {props.error.stack}
            </div>
        </div>
    );
}

错误:TypeError:props.error 未定义。 因此 <Redirect> 不会传递我的属性。拥有包含错误详细信息的顶级错误页面的最佳方法是什么?如果我在每个组件中检查 error ? .. ,它就不会是顶级页面,而是每个组件内的一条消息。

2个回答

您可以像这样定义自己的表示,

import React from 'react'

class ErrorBoundary extends React.Component {
    constructor(props) {
      super(props);
      this.state = { hasError: false, error: '', info: '', stack: '' }
    }
  
    static getDerivedStateFromError(error) {
      // Update state so the next render will show the fallback UI.
      return { hasError: true };
    }
  
    componentDidCatch(error, errorInfo) {
      // You can also log the error to an error reporting service
      // logErrorToMyService(error, errorInfo)
      this.setState({error, info: errorInfo, stack: error.stack})
    }
  
    render() {
      if (this.state.hasError) {
        // You can render any custom fallback UI
        return <h4>Something went wrong!</h4>;
      }
  
      return this.props.children; 
    }
}

export default ErrorBoundary

您可以根据需要呈现 errorinfostack 。您可以使用“react-json-view”包来很好地呈现 errorstack

并使用错误边界包装您的 App

<ErrorBoundary>
   <App />
</ErrorBoundary>
Amila Senadheera
2021-04-29

我们最终重定向到 /error?... ,并使用自定义参数字符串告诉 Error 组件要显示什么。设置 Error 对象时,我们设置了要捕获的所有数据项。

const [errorObj, setErrorObj] = useState({});

来自 Ajax,可能设置错误的位置:

catch (error) { 
    // We capture 2 data items for an error in a custom object: message and location.
    // Any other data items can also be in this custom object.
    setErrorObj({message: error.message, location: 'approvals.js: fetchTeleworkInfo'});
}

渲染时:

errorObj.message
    ?
        <Redirect to={generatePath('./error?msg=:errorMessage', 
                                   {errorMessage: formatError(errorObj)})} />
    :
        {/* Continue with normal render */}
        <div>...</div>

实用函数 formatError 将从 Error 对象生成一些编码字符串:

// Format error object into a string (expects errorObj.message and errorObj.location fields)
// Error string is encoded (and decoded in the Error component) to support URL passing
export function formatError(errorObj) {
    let result = '';
    if (errorObj) {
        if (errorObj.message) {
            result += errorObj.message;
        } 
        if (errorObj.location) {
            result += ' (' + errorObj.location + ')';
        }
    }
    return encodeURIComponent(result);
}

Error 组件可以通过 prop 或 URL 工作。这是它如何读取 URL 参数的一个示例:

export default function Error(props) {

    // Obtain URL Params (optional)
    // ----------------------------
    const queryStr = new URLSearchParams(useLocation().search); 

    let message = null;
    if (props.msg) {    // Error string from property
       message = props.msg;
    } else if (queryStr.get("msg")) {   // Error string from React-Router URL param
       message = queryStr.get("msg");
    }
    // Decode string since it always comes in encoded
    if (message) {
       message = decodeURIComponent(message);
    }

然后,Error 组件可以根据需要呈现/格式化错误并检查 message 字符串,例如

{message &&     
        <div>..</div>
    }
gene b.
2022-03-01