使用 Reactjs 更改路线时屏幕闪烁

THI*_*NIS 7 reactjs react-router-dom

我有一个简单的路由系统,其中有一个页面作为容器 ( Home Page),其中有两个部分(NewPageStoredPage).

\n

我将所有路由设置保留在一处,即 App.tsx 中。我这样做是为了保持集中并获得更好的控制(我不知道我是否做错了)。

\n

发生的问题是,当更改该部分时,它会闪烁,由于某种原因它会再次重新加载页面。

\n

注意:我使用react-router-guards

\n

应用程序TSX

\n
import HomePage from \'pages/HomePage\';\nimport StoredPage from \'pages/StoredPage\';\nimport { memo, useMemo } from \'react\';\nimport { BrowserRouter, Switch, Redirect } from \'react-router-dom\';\nimport { GuardedRoute, GuardProvider, Next } from \'react-router-guards\';\nimport { GuardFunctionRouteProps, GuardToRoute } from \'react-router-guards/dist/types\';\n\nexport const Main = memo(() => {\n    const RequireLoginGuard = (to: GuardToRoute, from: GuardFunctionRouteProps | null, next: Next) => next();\n\n    return (\n        <ErrorBoundary instance={instance}>\n            <BrowserRouter>\n                <GuardProvider guards={[RequireLoginGuard]} loading={() => <div>Loading Global</div>}>\n                    <Switch>\n                        <GuardedRoute exact path=\'/new\' loading={() => <div>Loading New Page</div>} component={HomePage} />\n                        <GuardedRoute exact path=\'/stored\' loading={() => <div>Loading Stored Page</div>} component={HomePage} />\n                        <GuardedRoute path=\'*\' component={() => <Redirect to=\'/new\' />} />\n                    </Switch>\n                </GuardProvider>\n            </BrowserRouter>\n        </ErrorBoundary>\n    );\n});\n
Run Code Online (Sandbox Code Playgroud)\n

主页.TSX

\n
import NewPage from \'pages/NewPage\';\nimport StoredPage from \'pages/StoredPage\';\nimport { useMemo } from \'react\';\nimport { Route, Router, Switch } from \'react-router-dom\';\nimport SectionTitle from \'xpi-black-ui/Common/SectionTitle\';\nimport Navigation from \'../../components/Navigation\';\nimport MainContainer, { SectionContainer } from \'./styles\';\n\nconst HomePage = () => {\n    const navigationItems = useMemo(\n        () => [\n            {\n                key: \'new\',\n                title: \'New Quotation\',\n                link: \'/new\',\n                component: () => <NewPage />,\n            },\n            {\n                key: \'stored\',\n                title: \'New Quotation 2\',\n                link: \'/stored\',\n                component: () => <StoredPage />,\n            },\n        ],\n        []\n    );\n\n    return (\n        <MainContainer>\n            <SectionContainer>Aaaaaaaaaaaaaaa</SectionContainer>\n            <SectionContainer isSecondary>\n                <SectionTitle>\n                    <Navigation />\n\n                    <div>C</div>\n                </SectionTitle>\n\n                <Switch>\n                    {navigationItems.map(({ key, link, component: PageComponent }) => (\n                        <Route key={key} path={link} component={PageComponent} exact />\n                    ))}\n                </Switch>\n            </SectionContainer>\n        </MainContainer>\n    );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

导航.TSX

\n
import { useCallback } from \'react\';\nimport { useLocation } from \'react-router-dom\';\nimport NavLink, { Container } from \'./styles\';\n\nconst Navigation = () => {\n    const { pathname } = useLocation();\n    const isActive = useCallback((linkPathSelected) => pathname === linkPathSelected, [pathname]);\n    const links = [\n        { key: \'new\', to: \'/new\', title: \'Criar Cota\xc3\xa7\xc3\xa3o\' },\n        { key: \'stored\', to: \'/stored\', title: \'Cota\xc3\xa7\xc3\xb5es Armazenadas\' },\n    ];\n\n    return (\n        <Container>\n            {links.map(({ key, to, title }) => (\n                <NavLink exact key={key} to={to} $isActive={isActive(to)}>\n                    {title}\n                </NavLink>\n            ))}\n        </Container>\n    );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

Dre*_*ese 5

据我所知,问题在于您的组件中定义数组属性的Homepage方式以及在将函数传递给组件时组件如何处理prop 的方式。navigationItemscomponentRoutecomponent

const navigationItems = useMemo(
  () => [
    {
      key: 'new',
      title: 'New Quotation',
      link: '/new',
      component: () => <NewPage />,    // <-- function
    },
    {
      key: 'stored',
      title: 'New Quotation 2',
      link: '/stored',
      component: () => <StoredPage />, // <-- function
    },
  ],
  []
);
Run Code Online (Sandbox Code Playgroud)

...

<Switch>
  {navigationItems.map(({ key, link, component: PageComponent }) => (
    <Route
      key={key}
      path={link}
      component={PageComponent} // <-- function passed through
      exact
    />
  ))}
</Switch>
Run Code Online (Sandbox Code Playgroud)

路线component

当您使用component(而不是下面的renderchildren)时,路由器将使用给定组件React.createElement创建新的React 元素。这意味着如果您为组件属性提供内联函数,则每次渲染都会创建一个新组件。这会导致卸载现有组件并安装新组件,而不仅仅是更新现有组件。当使用内联函数进行内联渲染时,请使用renderchildren属性(如下)。

navigationItems解决方案是根据组件的 props API定义对象属性Route。如果您要传递希望在componentprop 上渲染的组件,那么它们应该是对 React 组件的引用,而不是返回 JSX 的函数。

const navigationItems = useMemo(
  () => [
    {
      key: 'new',
      title: 'New Quotation',
      link: '/new',
      component: NewPage,
    },
    {
      key: 'stored',
      title: 'New Quotation 2',
      link: '/stored',
      component: StoredPage,
    },
  ],
  []
);
Run Code Online (Sandbox Code Playgroud)

...

<Switch>
  {navigationItems.map(({ key, link, ...props }) => (
    <Route key={key} exact path={link} {...props} />
  ))}
</Switch>
Run Code Online (Sandbox Code Playgroud)

您可能想对该link属性执行相同的操作,将其重命名为path,使其更符合其用途。

const navigationItems = useMemo(
  () => [
    {
      key: 'new',
      title: 'New Quotation',
      path: '/new',
      component: NewPage,
    },
    {
      key: 'stored',
      title: 'New Quotation 2',
      path: '/stored',
      component: StoredPage,
    },
  ],
  []
);
Run Code Online (Sandbox Code Playgroud)

...

<Switch>
  {navigationItems.map(({ key, ...props }) => (
    <Route key={key} exact {...props} />
  ))}
</Switch>
Run Code Online (Sandbox Code Playgroud)