React Router v6.10 受保护的路由问题

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

React Router v6.10 Protected Route problem

问题

I'm trying to build something with react that has some protected routes.

My main.jsx file:

import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./index.css";

import store from "./app/store";
import { Provider } from "react-redux";

import Root from "./components/Root";
import PublicLayout from "./components/PublicLayout";
import PersistLogin from "./components/PersistLogin";
import RequireAuthLayout from "./components/RequireAuthLayout";
import { ErrorPage, Home, Login, Logout, Register } from "./pages";

const router = createBrowserRouter([
  {
    path: "/*",
    element: <Root />,
    errorElement: <ErrorPage />,
    children: [
      {
        element: <PublicLayout />,
        children: [
          { path: "login", element: <Login /> },
          { path: "register", element: <Register /> },
        ],
      },
      {
        element: <PersistLogin />,
        children: [
          {
            element: <RequireAuthLayout />,
            children: [
              { path: "home", element: <Home /> },
              { path: "logout", element: <Logout /> },
            ],
          },
        ],
      },
    ],
  },
]);


ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <Provider store={store}>
      <RouterProvider router={router} />
    </Provider>
  </React.StrictMode>
);

Root.jsx:

import React from "react";
import { Outlet } from "react-router-dom";
import Header from "./Header";

const Root = () => {
  return (
    <>
      <Header />
      <main>
        <Outlet />
      </main>
    </>
  );
};

export default Root;

RequireAuthLayout.jsx:

import React from "react";
import { useLocation, Navigate, Outlet } from "react-router-dom";
import { useSelector } from "react-redux";
import { selectCurrentToken } from ".././features/auth/authSlice";

const RequireAuthLayout = () => {
  const token = useSelector(selectCurrentToken);
  const location = useLocation();

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

export default RequireAuthLayout;

PersistLogin.jsx:

import React, { useEffect } from "react";
import { Outlet } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { useRefreshMutation } from "../features/api/authApiSlice";
import { selectCurrentToken, setCredentials } from "../features/auth/authSlice";
import Loading from "../components/Loading";

const PersistLogin = () => {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  let content;

  useEffect(() => {
    const getAccessToken = async () => {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token && getAccessToken();
  }, []);

  if (isLoading) {
    content = <Loading />;
  } else if (isError) {
    content = <p>Bir hata oluştu, tekrar giriş yapınız!</p>;
  } else {
    <Outlet />;
  }

  return content;
};

export default PersistLogin;

PersistLogin is just sending a request to the endpoint to check if there is a cookie. If there is and valid, it sets the token in the redux store. But unfortunately, protected routes are not rendering. I mean there is no error and anything, but they are not rendering. The token is okay and everything but still...

Please help me.

英文:

I'm trying to build something with react that has some protected routes.

My main.jsx file:

import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import { createBrowserRouter, RouterProvider } from &quot;react-router-dom&quot;;
import &quot;./index.css&quot;;
import store from &quot;./app/store&quot;;
import { Provider } from &quot;react-redux&quot;;
import Root from &quot;./components/Root&quot;;
import PublicLayout from &quot;./components/PublicLayout&quot;;
import PersistLogin from &quot;./components/PersistLogin&quot;;
import RequireAuthLayout from &quot;./components/RequireAuthLayout&quot;;
import { ErrorPage, Home, Login, Logout, Register } from &quot;./pages&quot;;
const router = createBrowserRouter([
{
path: &quot;/*&quot;,
element: &lt;Root /&gt;,
errorElement: &lt;ErrorPage /&gt;,
children: [
{
element: &lt;PublicLayout /&gt;,
children: [
{ path: &quot;login&quot;, element: &lt;Login /&gt; },
{ path: &quot;register&quot;, element: &lt;Register /&gt; },
],
},
{
element: &lt;PersistLogin /&gt;,
children: [
{
element: &lt;RequireAuthLayout /&gt;,
children: [
{ path: &quot;home&quot;, element: &lt;Home /&gt; },
{ path: &quot;logout&quot;, element: &lt;Logout /&gt; },
],
},
],
},
],
},
]);
ReactDOM.createRoot(document.getElementById(&quot;root&quot;)).render(
&lt;React.StrictMode&gt;
&lt;Provider store={store}&gt;
&lt;RouterProvider router={router} /&gt;
&lt;/Provider&gt;
&lt;/React.StrictMode&gt;
);

Root.jsx:

import React from &quot;react&quot;;
import { Outlet } from &quot;react-router-dom&quot;;
import Header from &quot;./Header&quot;;
const Root = () =&gt; {
return (
&lt;&gt;
&lt;Header /&gt;
&lt;main&gt;
&lt;Outlet /&gt;
&lt;/main&gt;
&lt;/&gt;
);
};
export default Root;

RequireAuthLayout.jsx:

import React from &quot;react&quot;;
import { useLocation, Navigate, Outlet } from &quot;react-router-dom&quot;;
import { useSelector } from &quot;react-redux&quot;;
import { selectCurrentToken } from &quot;.././features/auth/authSlice&quot;;
const RequireAuthLayout = () =&gt; {
const token = useSelector(selectCurrentToken);
const location = useLocation();
return token ? (
&lt;Outlet /&gt;
) : (
&lt;Navigate to={&quot;/login&quot;} state={{ from: location }} replace /&gt;
);
};
export default RequireAuthLayout;

PersistLogin.jsx:

import React, { useEffect } from &quot;react&quot;;
import { Outlet } from &quot;react-router-dom&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;
import { useRefreshMutation } from &quot;../features/api/authApiSlice&quot;;
import { selectCurrentToken, setCredentials } from &quot;../features/auth/authSlice&quot;;
import Loading from &quot;../components/Loading&quot;;
const PersistLogin = () =&gt; {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
let content;
useEffect(() =&gt; {
const getAccessToken = async () =&gt; {
try {
const result = await refresh();
dispatch(setCredentials(result.data));
} catch (error) {
// console.log(error);
}
};
!token &amp;&amp; getAccessToken();
}, []);
if (isLoading) {
content = &lt;Loading /&gt;;
} else if (isError) {
content = &lt;p&gt;Bir hata oluştu, tekrar giriş yapınız!&lt;/p&gt;;
} else {
&lt;Outlet /&gt;;
}
return content;
};
export default PersistLogin;

PersistLogin is just sending a request to the endpoint to check if there is a cookie.
If there is and valid it sets the token in the redux store.
But unfourtunately protected routes are not rendering. I mean there is no error and anything but they are not rendering. The token is okey and everything but stil..

Please help me..

答案1

得分: 0

以下是翻译好的代码部分:

const PersistLogin = () => {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  let content;

  useEffect(() => {
    const getAccessToken = async () => {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token && getAccessToken();
  }, []);

  if (isLoading) {
    content = <Loading />;
  } else if (isError) {
    content = <p>一个错误发生请重新登录</p>;
  } else {
    content = <Outlet />; // <-- 设置内容
  }

  return content;
};

const PersistLogin = () => {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  let content = <Outlet />; // <-- 设置为 "默认" 内容;

  useEffect(() => {
    const getAccessToken = async () => {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token && getAccessToken();
  }, []);

  if (isLoading) {
    content = <Loading />;
  } else if (isError) {
    content = <p>一个错误发生请重新登录</p>;
  }

  return content;
};

const PersistLogin = () => {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  useEffect(() => {
    const getAccessToken = async () => {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token && getAccessToken();
  }, []);

  if (isLoading) {
    return <Loading />;
  }
  if (isError) {
    return <p>一个错误发生请重新登录</p>;
  }
  return <Outlet />;
};
英文:

The PersistLogin component appears to not be rendering an Outlet component for the nested routes to render their content into. &lt;Outlet /&gt; should be returned.

const PersistLogin = () =&gt; {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  let content;

  useEffect(() =&gt; {
    const getAccessToken = async () =&gt; {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token &amp;&amp; getAccessToken();
  }, []);

  if (isLoading) {
    content = &lt;Loading /&gt;;
  } else if (isError) {
    content = &lt;p&gt;Bir hata oluştu, tekrar giriş yapınız!&lt;/p&gt;;
  } else {
    content = &lt;Outlet /&gt;; // &lt;-- set content
  }

  return content;
};

or

const PersistLogin = () =&gt; {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  let content &lt;Outlet /&gt;; // &lt;-- set as &quot;default&quot; content;

  useEffect(() =&gt; {
    const getAccessToken = async () =&gt; {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token &amp;&amp; getAccessToken();
  }, []);

  if (isLoading) {
    content = &lt;Loading /&gt;;
  } else if (isError) {
    content = &lt;p&gt;Bir hata oluştu, tekrar giriş yapınız!&lt;/p&gt;;
  }

  return content;
};

or

const PersistLogin = () =&gt; {
  const [refresh, { isLoading, isError }] = useRefreshMutation();
  const dispatch = useDispatch();

  const token = useSelector(selectCurrentToken);

  useEffect(() =&gt; {
    const getAccessToken = async () =&gt; {
      try {
        const result = await refresh();
        dispatch(setCredentials(result.data));
      } catch (error) {
        // console.log(error);
      }
    };
    !token &amp;&amp; getAccessToken();
  }, []);

  if (isLoading) {
    return &lt;Loading /&gt;;
  }
  if (isError) {
    return &lt;p&gt;Bir hata oluştu, tekrar giriş yapınız!&lt;/p&gt;;
  }
  return &lt;Outlet /&gt;;
};

huangapple
  • 本文由 发表于 2023年4月4日 05:38:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75923962.html
匿名

发表评论

匿名网友

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

确定