【问题标题】:Flashing screen when changing route with Reactjs使用 Reactjs 更改路线时闪烁的屏幕
【发布时间】:2021-12-28 22:23:51
【问题描述】:

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

我将所有路线设置都放在一个地方,即 App.tsx 中。我这样做是为了保持集中并更好地控制(我不知道我是否做错了)。

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

注意:我使用react-router-guards

APP.TSX

import HomePage from 'pages/HomePage';
import StoredPage from 'pages/StoredPage';
import { memo, useMemo } from 'react';
import { BrowserRouter, Switch, Redirect } from 'react-router-dom';
import { GuardedRoute, GuardProvider, Next } from 'react-router-guards';
import { GuardFunctionRouteProps, GuardToRoute } from 'react-router-guards/dist/types';

export const Main = memo(() => {
    const RequireLoginGuard = (to: GuardToRoute, from: GuardFunctionRouteProps | null, next: Next) => next();

    return (
        <ErrorBoundary instance={instance}>
            <BrowserRouter>
                <GuardProvider guards={[RequireLoginGuard]} loading={() => <div>Loading Global</div>}>
                    <Switch>
                        <GuardedRoute exact path='/new' loading={() => <div>Loading New Page</div>} component={HomePage} />
                        <GuardedRoute exact path='/stored' loading={() => <div>Loading Stored Page</div>} component={HomePage} />
                        <GuardedRoute path='*' component={() => <Redirect to='/new' />} />
                    </Switch>
                </GuardProvider>
            </BrowserRouter>
        </ErrorBoundary>
    );
});

HOMEPAGE.TSX

import NewPage from 'pages/NewPage';
import StoredPage from 'pages/StoredPage';
import { useMemo } from 'react';
import { Route, Router, Switch } from 'react-router-dom';
import SectionTitle from 'xpi-black-ui/Common/SectionTitle';
import Navigation from '../../components/Navigation';
import MainContainer, { SectionContainer } from './styles';

const HomePage = () => {
    const navigationItems = useMemo(
        () => [
            {
                key: 'new',
                title: 'New Quotation',
                link: '/new',
                component: () => <NewPage />,
            },
            {
                key: 'stored',
                title: 'New Quotation 2',
                link: '/stored',
                component: () => <StoredPage />,
            },
        ],
        []
    );

    return (
        <MainContainer>
            <SectionContainer>Aaaaaaaaaaaaaaa</SectionContainer>
            <SectionContainer isSecondary>
                <SectionTitle>
                    <Navigation />

                    <div>C</div>
                </SectionTitle>

                <Switch>
                    {navigationItems.map(({ key, link, component: PageComponent }) => (
                        <Route key={key} path={link} component={PageComponent} exact />
                    ))}
                </Switch>
            </SectionContainer>
        </MainContainer>
    );
};

NAVIGATION.TSX

import { useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import NavLink, { Container } from './styles';

const Navigation = () => {
    const { pathname } = useLocation();
    const isActive = useCallback((linkPathSelected) => pathname === linkPathSelected, [pathname]);
    const links = [
        { key: 'new', to: '/new', title: 'Criar Cotação' },
        { key: 'stored', to: '/stored', title: 'Cotações Armazenadas' },
    ];

    return (
        <Container>
            {links.map(({ key, to, title }) => (
                <NavLink exact key={key} to={to} $isActive={isActive(to)}>
                    {title}
                </NavLink>
            ))}
        </Container>
    );
};

【问题讨论】:

    标签: reactjs react-router-dom


    【解决方案1】:

    据我所知,问题出在您的Homepage 组件中,您定义navigationItems 数组的component 属性的方式以及Route 组件在函数运行时如何处理component 属性传递给它。

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

    ...

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

    Route component:

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

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

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

    ...

    <Switch>
      {navigationItems.map(({ key, link, ...props }) => (
        <Route key={key} exact path={link} {...props} />
      ))}
    </Switch>
    

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

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

    ...

    <Switch>
      {navigationItems.map(({ key, ...props }) => (
        <Route key={key} exact {...props} />
      ))}
    </Switch>
    

    【讨论】:

    • 我真的很喜欢你的回答,我给了它。但即便如此,我仍然有同样的问题。任何的想法?我点击更改部分的菜单是 NavLink,它有什么相关的吗?
    • @THIAGODEBONIS 很有趣。行。认为您可以为上面的代码创建一个 running 代码和框,以重现我们可以实时检查和调试的问题?我不会怀疑这些链接,但很高兴看到像您这样的实时版本,看看可能存在什么问题或问题区域。
    • 看看能不能访问:codesandbox.io/s/bold-hellman-m0qnd?file=/src/components/…我在公司的电脑上,所以内网沙箱不跑了,我可以创建文件了。
    • @THIAGODEBONIS 是的,我可以访问。看起来它缺少 HomePage 组件声明和任何导航组件。
    • 抱歉,由于某种原因浏览器在这个网站上崩溃了,我在问题中发布了导航组件。
    【解决方案2】:

    Drew answer帮助了我,但要真正解决问题,我需要在Guard 加载中插入一些东西,在这种情况下我插入了HomePage 本身:

    <GuardProvider guards={[RequireLoginGuard]} loading={HomePage}>
        <Switch>
          <GuardedRoute exact path='/new' component={HomePage} />
          <GuardedRoute exact path='/stored' component={HomePage} />
          <GuardedRoute path='*' component={() => <Redirect to='/new' />} />
       </Switch>
    </GuardProvider>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-06
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      相关资源
      最近更新 更多