简体   繁体   English

使用 react-router-dom 在页面之间导航时重定向缓慢

[英]Slow redirecting while navigate between pages using react-router-dom

<Route path="/week" exact component={Week} />
<Route path="/all" exact render={() => {
                            return <AllPage />;
                          }}/>
<Route path="/chat" exact component={ChatRedirect} />

This is my routing file, I want to redirect between pages with a supersonic speed and after changing of routes there should be no any lag while redirecting the page.这是我的路由文件,我想以超音速在页面之间重定向,并且在更改路由后重定向页面时应该没有任何滞后。 My current scenario is when I redirect between page my browser url shows me updated url but my current page is not updated.我目前的情况是,当我在页面之间重定向时,我的浏览器 url 显示我更新了 url 但我当前的页面没有更新。

For example if I redirect from "/all" to "/chat" my url is updated to "/chat" but content of "/all" is showing for the moment and then after the content of "/chat" is showing.例如,如果我从“/all”重定向到“/chat” ,我的 url 将更新为“/chat” ,但“/all”的内容暂时显示,然后在“/chat”的内容显示之后。 So I want the solution like there should be updated content whenever I change the route.所以我想要这样的解决方案,就像每当我改变路线时应该有更新的内容。

I tried with including <BrowserRouter> tag and wrap my <switch> tag with <BrowserRouter> but it doesn't work.我尝试包含<BrowserRouter>标签并用<BrowserRouter> BrowserRouter> 包装我的<switch>标签,但它不起作用。 Then I tried with the react.lazy method component declaration with <Suspense> tag wrapping still facing the issue.然后我尝试使用带有<Suspense>标签包装的 react.lazy 方法组件声明仍然面临问题。

Here is my whole code file:这是我的整个代码文件:

import React, { Suspense, useEffect, useRef, useState } from "react";
import {
  useRouteMatch,
  withRouter,
  Route,
  Switch,
  useLocation,
  Redirect,
} from "react-router-dom";
import { ReflexContainer, ReflexElement, ReflexSplitter } from "react-reflex";

import { isMobileDevice } from "../utils/devices";
import { useSelector, useAppDispatch } from "../utils/hooks/general";
import { useActiveWorkspace } from "../utils/hooks/workspace";
import { useCurrentUser } from "../utils/hooks/user";
import { initialise } from "../redux/modules/app";

import SideNavigationDrawer from "./drawers/SideNavigation";

import { buildInboxProjectId } from "../utils/projects";
import { loadAwards, LOAD_AWARDS } from "../redux/modules/awards";
import { useCustomEventListener } from "react-custom-events";
import { loadNotes } from "../redux/modules/notes";

import { useWorkspaceUserPreference } from "../utils/hooks/userPreference";
import { updateWorkspaceUserPreferences } from "../redux/modules/userPreferences";
const Onboarding = React.lazy(() => import("../pages/onboarding/Onboarding"));
const ChatContainer = React.lazy(
  () => import("../components/chats/components/ChatContainer")
);
const Notifications = React.lazy(
  () => import("../components/chats/components/Notifications")
);
const AcceptInvitePage = React.lazy(() => import("../pages/AcceptInvite"));
const NotFoundPage = React.lazy(() => import("../pages/NotFound"));
const ProjectsPage = React.lazy(() => import("../pages/Projects"));
const Queue = React.lazy(() => import("../pages/Queue"));
const SubscriptionCreatePage = React.lazy(
  () => import("../pages/subscription/Create")
);
const SubscriptionPage = React.lazy(() => import("../pages/Subscription"));
const WorkspacePreferencesPage = React.lazy(
  () => import("../pages/WorkspacePreferences")
);

const ProfilePage = React.lazy(() => import("../pages/Profile"));
const OverduePage = React.lazy(() => import("../pages/Overdue"));
const Calendar = React.lazy(() => import("../pages/Calendar"));
const Notes = React.lazy(() => import("../pages/Notes"));
const NoteRedirect = React.lazy(() => import("./notes/menus/NoteRedirect"));
const Starred = React.lazy(() => import("../pages/Starred"));
const Week = React.lazy(() => import("../pages/Week"));

const ChatRedirect = React.lazy(
  () => import("./drawers/sideNavigation/chats/ChatRedirect")
);
const AllPage = React.lazy(() => import("../pages/All"));

const SIDEBAR_WIDTH = 300;
const SNAP_WIDTH = 30;
const DEFAULT_WINDOW_RESIZER_ENABLE = true;

const App: React.FC = () => {
  const match = useRouteMatch("*");
  const location = useLocation();
  const dispatch = useAppDispatch();
  const user = useCurrentUser();
  const activeWorkspace = useActiveWorkspace();
  const appInitialised = useSelector((state) => state.app?.initialised);
  const [screenHeight, setScreenHeight] = useState(0);
  const [screenWidth, setScreenWidth] = useState(0);
  const activeWorkspaceId = activeWorkspace ? activeWorkspace.id : null;
  const [baseRoute, ...otherRoutes] =
    match && match.url ? match.url.substr(1).split("/") : [];
  const projectId: string | undefined =
    baseRoute === "projects" && otherRoutes.length ? otherRoutes[0] : undefined;
  let from = { pathname: "/today" };
  let inviteId: string | null = null;

  if (location.state) {
    const state = location.state as any;
    if (state.inviteId) {
      inviteId = state.inviteId;
    } else if (state.from) {
      from = state.from;
    }
  }

  const hasInviteId = inviteId !== null;
  const isInviteAcceptPath = useRouteMatch("/invites/:inviteId/accept");

  const loadAwardsHandler = () => {
    if (user && activeWorkspaceId)
      dispatch(
        loadAwards({
          userId: user.id,
          workspaceId: activeWorkspaceId,
        })
      );
  };

  useCustomEventListener(LOAD_AWARDS, loadAwardsHandler);
  useEffect(() => {
    const url = location?.pathname;
    if (
      activeWorkspaceId &&
      user?.id &&
      (url === "/starred" ||
        url === "/queue" ||
        url === "/inbox" ||
        url?.startsWith("/project") ||
        url === "/today" ||
        url === "/all" ||
        url === "/overdue" ||
        url === "/week")
    ) {
      dispatch(
        loadAwards({
          userId: user.id,
          workspaceId: activeWorkspaceId,
        })
      );
    }
    if (activeWorkspaceId && user?.id && url.startsWith("/notes")) {
      dispatch(loadNotes(activeWorkspaceId));
    }
  }, [activeWorkspaceId, user, dispatch, location]);

  useEffect(() => {
    if (!appInitialised) {
      dispatch(
        initialise({
          workspaceId: activeWorkspaceId || undefined,
          projectId,
        })
      );
    }
  }, [dispatch, appInitialised, projectId, activeWorkspaceId]);

  useEffect(() => {
    // This is to fix the site for mobile browsers which set the viewport height
    // larger than the window causing everything to overflow...
    if (isMobileDevice()) {
      setScreenHeight(window.innerHeight);
      setScreenWidth(window.innerWidth);
    }
  }, []);

  const sideNavPreferences = useWorkspaceUserPreference("sideNavigation");
  const sideNavVisible = sideNavPreferences
    ? !sideNavPreferences.collapsed
    : true;

  const isCollapsing = useRef(false);
  const [snapWidth, setSnapWidth] = useState<number | null>(null);
  const collapseSideBar = (visible: boolean) => {
    if (activeWorkspaceId && !isCollapsing.current) {
      isCollapsing.current = true;
      dispatch(
        updateWorkspaceUserPreferences({
          userId: user.id,
          workspaceId: activeWorkspaceId,
          updateProps: {
            sideNavigation: {
              collapsed: visible,
            },
          },
        })
      ).finally(() => {
        isCollapsing.current = false;
      });
    }
  };

  if (appInitialised) {
    if (hasInviteId) {
      return <Redirect to={`/invites/${inviteId}/accept`} />;
    } else if (isInviteAcceptPath) {
      return (
        <Suspense fallback={<>Loading...</>}>
          <Route path="/invites/:inviteId/accept" exact>
            <AcceptInvitePage />
          </Route>
        </Suspense>
      );
    } else if (activeWorkspace) {
      return (
        <div
          className="overflow-hidden flex"
          style={{
            height: screenHeight || "100vh",
            width: screenWidth || "100vw",
          }}
        >
          <Suspense fallback={<>Loading...</>}>
            <ChatContainer />
            <Notifications />
          </Suspense>
          <ReflexContainer
            windowResizeAware={DEFAULT_WINDOW_RESIZER_ENABLE}
            className="flex"
            orientation="vertical"
          >
            <ReflexElement
              className="flex w-full"
              size={snapWidth ? snapWidth : sideNavVisible ? SIDEBAR_WIDTH : 65}
              maxSize={450}
              minSize={65}
              onStopResize={(args) => {
                //@ts-ignore
                const sideWidth = args.domElement?.offsetWidth;
                if (
                  sideWidth < SIDEBAR_WIDTH + SNAP_WIDTH &&
                  sideWidth > SIDEBAR_WIDTH - SNAP_WIDTH
                ) {
                  setSnapWidth(
                    snapWidth === SIDEBAR_WIDTH
                      ? SIDEBAR_WIDTH - 1
                      : SIDEBAR_WIDTH
                  );
                } else {
                  setSnapWidth(null);
                }
              }}
              onResize={(args) => {
                //@ts-ignore
                const sideWidth = args.domElement?.offsetWidth;
                if (sideWidth < 210 && sideNavVisible) {
                  collapseSideBar(sideNavVisible);
                } else if (sideWidth > 1 && !sideNavVisible) {
                  collapseSideBar(sideNavVisible);
                }
              }}
            >
              <SideNavigationDrawer />
            </ReflexElement>

            <ReflexSplitter />

            <ReflexElement className="flex">
              <main className="w-full h-full overflow-hidden relative">
                <Suspense fallback={<>Loading...</>}>
                  <Switch location={location}>
                    <Redirect from="/login" to={from} />
                    <Redirect from="/signup" to={from} />
                    <Redirect from="/" to="/today" exact />
                    <Route path="/profile" exact component={ProfilePage} />
                    <Route
                      path="/preferences"
                      exact
                      component={WorkspacePreferencesPage}
                    />
                    <Route
                      path="/subscription"
                      exact
                      render={() => {
                        if (activeWorkspace.createdBy !== user.id) {
                          return <Redirect to="/" />;
                        } else {
                          return <SubscriptionPage />;
                        }
                      }}
                    />
                    <Route
                      path="/subscription/create"
                      exact
                      render={() => {
                        if (activeWorkspace.createdBy !== user.id) {
                          return <Redirect to="/" />;
                        } else if (activeWorkspace.subscription) {
                          return <Redirect to="/subscription" />;
                        } else {
                          return <SubscriptionCreatePage />;
                        }
                      }}
                    />
                    <Route path="/starred" exact component={Starred} />
                    <Route path="/queue" exact component={Queue} />
                    <Route
                      path="/today"
                      exact
                      render={() => {
                        return <Week isToday />;
                      }}
                    />
                    <Route path="/week" exact component={Week} />
                    <Route
                      path="/all"
                      exact
                      render={() => {
                        return <AllPage />;
                      }}
                    />
                    <Route path="/overdue" exact component={OverduePage} />
                    <Route
                      path={["/inbox", "/projects/:projectId"]}
                      exact
                      render={(routeProps) => {
                        let projectId = "",
                          isAutoGrouping = true;

                        if (routeProps.match.path === "/inbox") {
                          isAutoGrouping = false;
                          projectId = buildInboxProjectId(
                            user,
                            activeWorkspace
                          );
                        } else {
                          projectId = (
                            routeProps.match.params as { projectId: string }
                          ).projectId;
                        }

                        return (
                          <ProjectsPage
                            projectId={projectId}
                            isAutoGrouping={isAutoGrouping}
                          />
                        );
                      }}
                    />
                    <Route path="/notes" exact component={NoteRedirect} />
                    <Route path="/calendar" exact component={Calendar} />
                    <Route path="/chat" exact component={ChatRedirect} />
                    <Route
                      path={["/chat/:chatSID"]}
                      exact
                      render={(routeProps) => {
                        let sid = routeProps.match?.params?.chatSID;
                        return <ChatRedirect sid={sid} />;
                      }}
                    />

                    <Route
                      path={["/notes/:noteId"]}
                      exact
                      render={(routeProps) => {
                        let noteId = routeProps.match?.params?.noteId;
                        return <Notes noteId={noteId} />;
                      }}
                    />

                    <Route component={NotFoundPage} />
                  </Switch>
                </Suspense>
              </main>
            </ReflexElement>
          </ReflexContainer>
        </div>
      );
    } else {
      return (
        <Suspense fallback={<>Loading...</>}>
          <Onboarding />
        </Suspense>
      );
    }
  } else {
    return null;
  }
};

export default withRouter(App);

I am using "react-router-dom": "^5.3.0",我正在使用"react-router-dom": "^5.3.0",

you can use Framer-motion package here.你可以在这里使用 Framer-motion package。 change your route component wrappers from this从此更改您的路由组件包装器

return
<div>

</div>

with this有了这个

<motion.div>

</motion.div>

and wrap your whole app component with animatePresence并用 animatePresence 包裹你的整个应用程序组件

<AnimatePresence
exitBeforeEnter={true}
>

</AnimatePresence>

and check the documentation here https://www.framer.com/docs/并在此处查看文档https://www.framer.com/docs/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM