【问题标题】:React: Redirect to an error page with error message/stack trace using React RouterReact:使用 React Router 重定向到带有错误消息/堆栈跟踪的错误页面
【发布时间】:2021-04-29 14:56:00
【问题描述】:

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

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

假设在某些低级组件中出现故障。我得到一个带有.message 和.stack 的error 对象。我需要我的Error 组件在路由器&lt;Redirect /&gt; 之后显示错误详细信息。

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>
    );
}

Error: TypeError: props.error is undefined . 所以&lt;Redirect&gt; 没有传递我的属性。拥有包含错误详细信息的顶级错误页面的最佳方式是什么?如果我在每个组件中检查error ? ..,它就不是顶级页面,而是每个组件内部的一条消息。

【问题讨论】:

标签: reactjs react-router react-router-dom


【解决方案1】:

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

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

您可以根据需要渲染error、info 和stack。您可以使用 'react-json-view' 包很好地渲染 error 和 stack。

并用你的错误边界包裹你的App,

<ErrorBoundary>
   <App />
</ErrorBoundary>

【讨论】:

  • @gene b.,这应该是使用reactjs处理您的场景的理想方式
【解决方案2】:

我们刚刚使用自定义参数字符串重定向到 /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 将从错误对象中生成一些编码字符串:

// 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);
}

错误组件可以通过 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);
    }

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

    {message &&     
        <div>..</div>
    }

【讨论】:

    猜你喜欢
    • 2018-11-27
    • 2018-09-13
    • 2015-08-04
    • 2015-11-19
    • 2015-04-07
    • 2018-09-19
    • 1970-01-01
    • 2013-12-07
    • 2020-12-01
    相关资源
    最近更新 更多