typescript React路由器导航(-1)(useNavigate挂钩)工作不正常

6kkfgxo0  于 2023-03-04  发布在  TypeScript
关注(0)|答案(2)|浏览(331)

当我使用navigate(-1)useNavigate钩子)时,react-router出现问题。
例如,我在'/products'PRODUCTS)上,点击按钮(使用useNavigate('...')),现在我在'/products/create'PRODUCT_CREATE)上,然后我返回使用navigate(-1),有时我可能会随机进入'/users'USERS)或'/products'PRODUCTS)。
这是一件很善变的事情,也许你对此有所了解。
app.routes.ts

// ======= private route ======= //
const PrivateRoute: FC<RouteI> = ({ element: Element, session, hasSidebar }) => {
  console.log(session);
  return session ? (
    <Suspense fallback={<LinearProgress />}>
      <SidebarGrid element={Element} hasSidebar={hasSidebar} />
    </Suspense>
  ) : (
    <Navigate to={APP_PATH.SIGN_IN} />
  );
};
// ======= public route ======= //
const PublicRoute: FC<RouteI> = ({ element: Element, session }) => (
  <Suspense fallback={<LinearProgress />}>
    {session ? <Navigate to={APP_PATH.USERS} /> : <Element />}
  </Suspense>
);
// ======= pages ======= //
const SignInPage = React.lazy(() => import('./shared/pages/sign-in'));
const ResetPasswordPage = React.lazy(() => import('./shared/pages/reset-password'));
const ProductsPage = React.lazy(() => import('./shared/pages/products'));
const ProductCreatePage = React.lazy(() => import('./shared/pages/product-create'));
const ProductDetailsPage = React.lazy(() => import('./shared/pages/product-details'));
const ProductEditPage = React.lazy(() => import('./shared/pages/product-edit'));
const ProductTypesPage = React.lazy(() => import('./shared/pages/product-types'));
const UsersPage = React.lazy(() => import('./shared/pages/users'));
const UserDetailsPage = React.lazy(() => import('./shared/pages/user-details'));
const ProfilePage = React.lazy(() => import('./shared/pages/profile'));
const OrdersPage = React.lazy(() => import('./shared/pages/orders'));
const AdministrationPage = React.lazy(() => import('./shared/pages/administration'));
const SubscriptionsPage = React.lazy(() => import('./shared/pages/subscriptions'));

const AppRoutes = () => {
  const session = useSelector(userSessionSelector);
  
  const {
    SIGN_IN,
    PRODUCTS,
    PRODUCT_CREATE,
    PRODUCT_DETAILS,
    PRODUCT_EDIT,
    PRODUCTS_TYPES,
    USERS,
    USER_DETAILS,
    RESET_PASSWORD,
    PROFILE,
    ORDERS,
    ADMINISTRATION,
    SUBSCRIPTIONS
  } = APP_PATH;

  useEffect(() => {
    if (!session) {
      return;
    }

    RequestNotificationPermissions();
  }, [session]);

  return (
    <Routes>
      {/* PRIVATE */}
      <Route path={PRODUCTS} element={<PrivateRoute session={session} element={ProductsPage} hasSidebar />} />
      <Route path={PRODUCT_CREATE} element={<PrivateRoute session={session} element={ProductCreatePage} hasSidebar />} />
      <Route path={PRODUCT_DETAILS} element={<PrivateRoute session={session} element={ProductDetailsPage} hasSidebar />} />
      <Route path={PRODUCT_EDIT} element={<PrivateRoute session={session} element={ProductEditPage} hasSidebar />} />
      <Route path={PRODUCTS_TYPES} element={<PrivateRoute session={session} element={ProductTypesPage} hasSidebar />} />
      <Route path={USERS} element={<PrivateRoute session={session} element={UsersPage} hasSidebar />} />
      <Route path={USER_DETAILS} element={<PrivateRoute session={session} element={UserDetailsPage} hasSidebar />} />
      <Route path={PROFILE} element={<PrivateRoute session={session} element={ProfilePage} hasSidebar />} />
      <Route path={ORDERS} element={<PrivateRoute session={session} element={OrdersPage} hasSidebar />} />
      <Route path={ADMINISTRATION} element={<PrivateRoute session={session} element={AdministrationPage} hasSidebar />} />
      <Route path={SUBSCRIPTIONS} element={<PrivateRoute session={session} element={SubscriptionsPage} hasSidebar />} />

      {/* PUBLIC */}
      <Route path={SIGN_IN} element={<PublicRoute session={session} element={SignInPage} />} />
      <Route path={RESET_PASSWORD} element={<PublicRoute session={session} element={ResetPasswordPage} />} />

      {/* DEFAULT */}
      <Route path='/' element={<Navigate to={session ? USERS : SIGN_IN} />} />
      <Route path='*' element={<Navigate to={session ? USERS : SIGN_IN} />} />
    </Routes>
  );
};

我尝试使用navigate()与选项{ replace: true },但它不工作。

juzqafwq

juzqafwq1#

我明白了!对于SPA应用程序,我不应该在navigate('/some/route', { replace: true })中使用选项替换。我删除了洞项目中的每一个{ replace: true },它工作了!

e4eetjau

e4eetjau2#

FWIW我认为所有的Navigate组件之间的公共和私人路线在您的路线*应该重定向,即更换,行动。我认为使用正常的推行动是离开历史堆栈在坏的形状,例如,留下一些"重定向"的条目在历史堆栈中,用户可以导航回来。

// ======= private route ======= //
const PrivateRoute: FC<RouteI> = ({ element: Element, session, hasSidebar }) => {
  console.log(session);
  return session ? (
    <Suspense fallback={<LinearProgress />}>
      <SidebarGrid element={Element} hasSidebar={hasSidebar} />
    </Suspense>
  ) : (
    <Navigate to={APP_PATH.SIGN_IN} replace /> // <-- redirect
  );
};
// ======= public route ======= //
const PublicRoute: FC<RouteI> = ({ element: Element, session }) => (
  <Suspense fallback={<LinearProgress />}>
    {session
      ? <Navigate to={APP_PATH.USERS} replace /> // <-- redirect
      : <Element />
    }
  </Suspense>
);
const AppRoutes = () => {
  ...

  return (
    <Routes>
      {/* PRIVATE */}
      <Route
        path={PRODUCTS}
        element={<PrivateRoute session={session} element={ProductsPage} hasSidebar />}
      />
      <Route
        path={PRODUCT_CREATE}
        element={<PrivateRoute session={session} element={ProductCreatePage} hasSidebar />}
      />
      <Route
        path={PRODUCT_DETAILS}
        element={<PrivateRoute session={session} element={ProductDetailsPage} hasSidebar />}
      />
      <Route
        path={PRODUCT_EDIT}
        element={<PrivateRoute session={session} element={ProductEditPage} hasSidebar />}
      />
      <Route
        path={PRODUCTS_TYPES}
        element={<PrivateRoute session={session} element={ProductTypesPage} hasSidebar />}
      />
      <Route
        path={USERS}
        element={<PrivateRoute session={session} element={UsersPage} hasSidebar />}
      />
      <Route
        path={USER_DETAILS}
        element={<PrivateRoute session={session} element={UserDetailsPage} hasSidebar />}
      />
      <Route
        path={PROFILE}
        element={<PrivateRoute session={session} element={ProfilePage} hasSidebar />}
      />
      <Route
        path={ORDERS}
        element={<PrivateRoute session={session} element={OrdersPage} hasSidebar />}
      />
      <Route
        path={ADMINISTRATION}
        element={<PrivateRoute session={session} element={AdministrationPage} hasSidebar />}
      />
      <Route
        path={SUBSCRIPTIONS}
        element={<PrivateRoute session={session} element={SubscriptionsPage} hasSidebar />}
      />

      {/* PUBLIC */}
      <Route
        path={SIGN_IN}
        element={<PublicRoute session={session} element={SignInPage} />}
      />
      <Route
        path={RESET_PASSWORD}
        element={<PublicRoute session={session} element={ResetPasswordPage} />}
      />

      {/* DEFAULT */}
      <Route
        path='/'
        element={<Navigate to={session ? USERS : SIGN_IN} replace />} // <-- redirect
      />
      <Route
        path='*'
        element={<Navigate to={session ? USERS : SIGN_IN} replace />} // <-- redirect
      />
    </Routes>
  );
};

建议的改进

为了使代码更***DRY***,我还建议将路由保护组件转换为布局路由组件,以便在每个组件上呈现一组嵌套的路由。
示例:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
希望大家能清楚地看到这在多大程度上简化了代码,提高了可读性和可维护性。

相关问题