【问题标题】:reset error boundary on back journey using useErrorHandler hook from react-error-boundary使用 react-error-boundary 中的 useErrorHandler 钩子在回程中重置错误边界
【发布时间】:2022-08-05 01:16:25
【问题描述】:

我正在使用 react-error-boundary 包来显示回退 UI,以防应用程序抛出任何错误。这个包对我来说很好用。如果我使用浏览器后退按钮转到以前的页面,我需要了解如何重置应用程序错误状态,因为转到以前的页面也会显示回退 UI 而不是原始组件。无论如何我们可以渲染原始组件吗?

在下面的代码中,用户将在 Page2 上抛出错误,因为我将空对象作为道具传递。在这种情况下,它将显示后备屏幕。如果我点击后退按钮,后备屏幕也会显示在 Page1 上,这是我不想要的。

应用程序.js

const errorHandler = (error) =>{
      console.log(error)
}

<BrowserRouter basename={\'/bookingtool/obt/\'}>
     <ErrorBoundary FallbackComponent={Fallback} onError={errorHandler}>
          <Routes>
               <Route path=\"/page1\" element={<Page1 PageName=\"Page1\" />} />
               <Route path=\"/page2\" element={<Page2 PageName={{}} /> } />
          </Routes>
    <ErrorBoundary />
</BrowserRouter>

Page1.js

import { useErrorHandler } from \'react-error-boundary\';
const Page1 = ({PageName}) =>{
     return(<p>{PageName}</p>)
}

Page2.js

import { useErrorHandler } from \'react-error-boundary\';
const Page2 = ({PageName}) =>{
     return(<p>{PageName}</p>)
}

后备.js

import React from \"react\";

const Fallback= (props) => {
    return(<h1>Something went wrong</h1>)
}

    标签: reactjs react-error-boundary


    【解决方案1】:

    &lt;ErrorBoundary /&gt; 提供key。每当key 更改时,错误边界就会被重置。

    在您的情况下,使用 useLocation().pathname 作为 key 意味着它会在路径更改时重置:

    const location =  useLocation();
    const [path, setPath] = useState(location.pathname);
    useLayoutEffect(
      () => setPath(location.pathname),
      [location.pathname]
    );
    // ...
    return (
      <ErrorBoundary key={path}>
        {/* ... */}
      </ErrorBoundary>
    )
    

    作为一个单独的建议,我会将错误处理移到 Layout 组件中。这将允许在发生错误时保持导航,这是很好的用户体验。

    一个基本的example here

    【讨论】:

      【解决方案2】:

      当您离开时尝试重置错误状态:

      const Fallback= ({ error, resetErrorBoundary} ) => {
          const location = useLocation();
          const errorLocation = useRef(location.pathname);
          useEffect(() => {
              if (location.pathname !== errorLocation.current) {
                  resetErrorBoundary();
              }
          },[location.pathname])
          return(<h1>Something went wrong</h1>)
      }
      

      【讨论】:

        【解决方案3】:

        您可以使用以下方式强制重新渲染错误边界, 首先制作一个单独的功能组件来保存错误边界并将监听器添加到历史记录

        import { createBrowserHistory } from "history";
        const history = createBrowserHistory();
        //a fallback component
        const ErrorFallback = () => {
         return <>
           <h1>Something went wrong.</h1>
           <button onClick={() => {
              history.back();
            }}>go back </button>
          </>
        }
         
        function RoutesContainer() {
         const [update, setUpdate] = useState(false);
         let navigate = useNavigate();
        const historyChange = () => {
        if (window.location.pathname !== history.location.pathname) {
          navigate(window.location.pathname, { replace: true });
        }
        };
        useEffect(() => {
         history.listen(historyChange)
        }, [historyChange])
        
         return <ErrorBoundary key={window.location.pathname}  FallbackComponent={ErrorFallback}>
        <Routes>
          <Route path="/page1" element={<Page1 PageName="Page1" />} />
          <Route path="/page2" element={<Page2 PageName={{}} />} />
        </Routes>
         </ErrorBoundary>
          }
        

        当你从page2回到page1的时候,history.location.pathname会有值“page2”,因为你按回,这个值将不匹配window.location.pathname,因为window.location.pathname有值“page1”,在这个阶段,我们将导航到 window.location.pathname,并使用这个值作为我们错误边界组件中的键。在写这个答案的时候,我使用 react-router-dom V6 和 react v18

        一个完整的用例演示在这里

            import React, { useEffect, useState } from 'react';
            import { BrowserRouter, Link, Route, Routes } from 'react-router-dom';
            import { createBrowserHistory } from "history";
            import { useNavigate } from "react-router-dom";
            import { ErrorBoundary } from 'react-error-boundary'
        
            const history = createBrowserHistory();
        
            const ErrorFallback = () => {
              return <>
                <h1>Something went wrong.</h1>
                <button onClick={() => {
                  history.back();
                }}>go back </button>
              </>
            }
            const Page1 = ({ PageName }) => {
              return (<p>{PageName}
                <Link to={'/page2'} >page 2</Link>
              </p>)
            }
        
            const Page2 = ({ PageName }) => {
              return (<p>{PageName}</p>)
            }
            function RoutesContainer() {
              const [update, setUpdate] = useState(false);
              let navigate = useNavigate();
        
              const historyChange = () => {
                if (window.location.pathname !== history.location.pathname) {
                  navigate(window.location.pathname, { replace: true });
                }
              };
        
              useEffect(() => {
                history.listen(historyChange)
              }, [historyChange])
        
              return <ErrorBoundary key={window.location.pathname}  FallbackComponent={ErrorFallback}>
                <Routes>
                  <Route path="/page1" element={<Page1 PageName="Page1" />} />
                  <Route path="/page2" element={<Page2 PageName={{}} />} />
                </Routes>
              </ErrorBoundary>
            }
        
        
            function App() {
              return (
                <BrowserRouter><RoutesContainer /></BrowserRouter>
              );
            }
        
            export default App;
        

        【讨论】:

          猜你喜欢
          • 2022-12-02
          • 2021-07-28
          • 1970-01-01
          • 2023-02-21
          • 1970-01-01
          • 1970-01-01
          • 2020-01-16
          • 1970-01-01
          相关资源
          最近更新 更多