刷新页面会导致页面变空白,并引发navigate()错误。

huangapple go评论72阅读模式
英文:

Refreshing the page causes the page to be rendered blank and navigate() error is thrown

问题

I have this simple hybrid SPA build with Astro, React, and RRDv6
路由树:

  • localhost/ ------------------(公共页面)
  • localhost/login ------------(管理员登录页面)
  • localhost/admin/home ---(管理员仪表板页面)

当我成功登录并重定向到管理员仪表板页面时,没有任何错误或警告。我尝试刷新页面以模拟刷新仪表板以通过API从数据库中获取最新数据。相反,我在控制台日志中遇到了以下错误,并且我的页面呈现为空白。

> 未捕获的错误:useNavigate() 只能在 <Router> 组件的上下文中使用。

我是否遗漏了RRDv6的概念,或者遗漏了重要的内容?

环境:node 16.13.0,npm 8.3.0
依赖:@astrojs/react 2.0.2,astro 2.0.16,react 18.2.0,react-router-dom 6.11.1
脚本:dev = astro dev
命令:npm run dev

路由:

export default function Admin() {
  const [cookie, setCookie, removeCookie] = useCookies(['token']);

  const PrivateRoute = () => {
    const location = useLocation()

    const isAuthenticated = () => {
      return cookie.token !== null && cookie.token !== undefined;
    };

    return isAuthenticated()
      ? <Outlet />
      : <Navigate to="/admin" replace state={{ from: location }} />;
  };

  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<AdminLogin />} />
        <Route path="/admin" element={<PrivateRoute />}>
          <Route path="home" element={<AdminHome />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

管理员仪表板:

export default function AdminHome() {
  const [cookie, setCookie, removeCookie] = useCookies(['token']);
  const [doLogout, setDoLogout] = useState(false)

  const navigate= useNavigate()

  useEffect(() => {
    if (doLogout) {
      removeCookie('token', { sameSite: 'none', secure: true })
      navigate('/login')
    }
  }, [doLogout])

  return (
    <div>
      <AdminAppbar cookie={cookie} logout={setDoLogout} />
      <AdminBlog/>
    </div>
  );
}
英文:

I have this simple hybrid SPA build with Astro, React, and RRDv6
Route tree:

˫ localhost/ ------------------(public page)
˫ localhost/login ------------(admin login page)
˪ localhost/admin/home ---(admin dashboard page)

When I have successfully logged in and redirected to admin dashboard page, no error or any warning is present. I tried to refresh the page to simulate refreshing dashboard to fetch latest data from database through API. Instead I am having this error in my console log and my page is rendered blank.

> Uncaught Error: useNavigate() may be used only in the context of a
> &lt;Router&gt; component.

Am I missing the RRDv6 concept, or missing something that is important?

env: node 16.13.0, npm 8.3.0
deps: @astrojs/react 2.0.2, astro 2.0.16, react 18.2.0, react-router-dom 6.11.1
script: dev = astro dev
cmd: npm run dev

Routes:

export default function Admin() {
  const [cookie, setCookie, removeCookie] = useCookies([&#39;token&#39;]);

  const PrivateRoute = () =&gt; {
    const location = useLocation()

    const isAuthenticated = () =&gt; {
      return cookie.token !== null &amp;&amp; cookie.token !== undefined;
    };

    return isAuthenticated()
      ? &lt;Outlet /&gt;
      : &lt;Navigate to=&quot;/admin&quot; replace state={{ from: location }} /&gt;;
  };

  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/login&quot; element={&lt;AdminLogin /&gt;} /&gt;
        &lt;Route path=&quot;/admin&quot; element={&lt;PrivateRoute /&gt;}&gt;
          &lt;Route path=&quot;home&quot; element={&lt;AdminHome /&gt;} /&gt;
        &lt;/Route&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

Admin Dashboard:

export default function AdminHome() {
  const [cookie, setCookie, removeCookie] = useCookies([&#39;token&#39;]);
  const [doLogout, setDoLogout] = useState(false)

  const navigate= useNavigate()

  useEffect(() =&gt; {
    if (doLogout) {
      removeCookie(&#39;token&#39;, { sameSite: &#39;none&#39;, secure: true })
      navigate(&#39;/login&#39;)
    }
  }, [doLogout])

  return (
    &lt;div&gt;
      &lt;AdminAppbar cookie={cookie} logout={setDoLogout} /&gt;
      &lt;AdminBlog/&gt;
    &lt;/div&gt;
  );
}

答案1

得分: 0

The only issues I see in the code are:

  • PrivateRoute 组件声明在另一个 React 组件内部。每当父组件重新渲染时,都会创建一个新的 "PrivateRoute" 实例,而该组件的整个 React 树将被销毁,然后新的 "PrivateRoute" 实例将被挂载。通常情况下,应该单独声明 React 组件。
  • isAuthenticated 评估为假值时,受保护的路由将重定向到自身。这可能会创建一个渲染循环,这就是页面为空的原因。您要保护的路由不应该重定向到其他受保护的路由。

请更新 PrivateRoute 以重定向到认证路由。

英文:

The only issues I see in the code are:

  • The PrivateRoute component is declared inside another React component. Each time the parent component renders, a new "instance" of PrivateRoute is created and that component's entire ReactTree is torn down and the new "instance" mounted. React components generally should be declared on their own.

  • The protected route is redirecting to itself when the isAuthenticated evaluates falsey. This is likely creating a render loop which is why the page is blank. Routes you are protecting should not redirect to other protected routes.

    Update PrivateRoute to redirect to the authentication route.

const PrivateRoute = () =&gt; {
  const location = useLocation();
  const [cookie, setCookie, removeCookie] = useCookies([&#39;token&#39;]);

  const isAuthenticated = cookie.token !== null &amp;&amp; cookie.token !== undefined;

  return isAuthenticated
    ? &lt;Outlet /&gt;
    : (
      &lt;Navigate
        to=&quot;/login&quot; // &lt;-- redirect to non-protected route
        replace
        state={{ from: location }}
      /&gt;
    );
};
export default function Admin() {
  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/login&quot; element={&lt;AdminLogin /&gt;} /&gt;
        &lt;Route path=&quot;/admin&quot; element={&lt;PrivateRoute /&gt;}&gt;
          &lt;Route path=&quot;home&quot; element={&lt;AdminHome /&gt;} /&gt;
        &lt;/Route&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

huangapple
  • 本文由 发表于 2023年5月18日 11:22:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76277519.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定