英文:
React Router v6, guarded routes using Context API
问题
createBrowserRouter 使用 React Router,可以在此上下文中访问AppContext 信息。你可以通过以下方式来实现在你的场景中访问上下文信息:
import { useNavigate, useLocation } from 'react-router-dom';
function ProtectedRoute({ element: Component, ...rest }) {
    const ctx = useContext(AppContext);
    const navigate = useNavigate();
    const location = useLocation();
    if (ctx.token !== "") {
        return <Component {...rest} />;
    } else {
        // Redirect to the login page and preserve the current location state
        navigate('/login', { state: { from: location } });
        return null;
    }
}
通过使用useNavigate 和 useLocation 钩子,你可以轻松地在用户未登录时将用户重定向到登录页面,并在登录后返回到原来的页面。
英文:
I have the following setup:
App.js
import AppContext from './context/AppContext.js';
import router from './routes/routes.js';
function App() {
    const [token, setToken] = useState("");
    
    function login(token) {
        setToken(token);
    }
    return (
        <React.StrictMode>
            <AppContext.Provider value={{ token, login }}>
                <RouterProvider router={router} />
            </AppContext.Provider>
        </React.StrictMode>
    );
}
export default App;
routes.js
export default createBrowserRouter([
    {
        path: "/",
        element: <Root />,
        children: [
            {
                path: "home",
                element: <Home />
            },
            {
                path: "admin",
                element: <ProtectedRoute element={Admin} />
            },
            {
                path: "login",
                element: <Login />
            }
        ]
    }
]);
ProtectedRoute.js
export default function ProtectedRoute({ element: Component, ...rest }) {
    const ctx = useContext(AppContext);
    return (
        ctx.token !== "" ? <Component /> : <Navigate to="/login" />
    );
}
I want to be able check if the user is logged in by accessing information from a context, however the returned object always contains the default values. Is there a way to access context information with createBrowserRouter in this scenario?
答案1
得分: 2
The protected route component should be refactored to be rendered as a layout route component by rendering an Outlet instead of some passed prop.
import { Navigate, Outlet } from 'react-router-dom';
export default function ProtectedRoute() {
  const { token } = useContext(AppContext);
  return token
    ? <Outlet />
    : <Navigate to="/login" replace />;
}
export default createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      { path: "home", element: <Home /> },
      {
        element: <ProtectedRoute />,
        children: [
          {
            path: "admin",
            element: <Admin />
          },
          // ... other protected routes
        ],
      },
      { path: "login", element: <Login /> }
      // ... other unprotected routes
    ]
  }
]);
英文:
The protected route component should be refactored to be rendered as a layout route component by rendering an Outlet instead of some passed prop.
import { Navigate, Outlet } from 'react-router-dom';
export default function ProtectedRoute() {
  const { token } = useContext(AppContext);
  return token
    ? <Outlet />
    : <Navigate to="/login" replace />;
}
export default createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      { path: "home", element: <Home /> },
      {
        element: <ProtectedRoute />,
        children: [
          {
            path: "admin",
            element: <Admin />
          },
          // ... other protected routes
        ],
      },
      { path: "login", element: <Login /> }
      // ... other unprotected routes
    ]
  }
]);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论