reactjs React layout状态更改重新呈现outlet中的子路由[duplicate]

qfe3c7zg  于 12个月前  发布在  React
关注(0)|答案(1)|浏览(232)

此问题在此处已有答案

Search field kicks me out on input field after 1 letter(2个答案)
It's okay to declare other components inside a component?(3个答案)
5天前关闭。
我正在做一个react应用程序,它使用一个布局来显示传递给它的路由。布局有一个头部和一个可以打开和关闭的侧边栏。当侧边栏打开或关闭时,它会导致在出口中显示的页面重新呈现。除了页面将与API交互外,这不是什么大问题(目前做的使用效果)这是触发每次抽屉打开或关闭,这似乎超级不必要和效率低下。
我试过把插座包在一个备忘录里,以防止重新渲染,但没有任何效果。
版面配置:

//react
import { Outlet } from 'react-router-dom';
import { useState } from 'react';

//mui
import { styled } from '@mui/material/styles';

//project
import { Header } from '../features/Header';
import { SideBar } from '../features/SideBar';
import { BackgroundBox } from '../core/BackgroundBox';

// ==============================|| MAIN LAYOUT ||============================== //

const MainLayout = () => {
  const drawerWidth = 240;

  const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(
    ({ theme, open }) => ({
      flexGrow: 1,
      padding: theme.spacing(3),
      transition: theme.transitions.create('margin', {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen
      }),
      marginLeft: 0,
      ...(open && {
        transition: theme.transitions.create('margin', {
          easing: theme.transitions.easing.easeOut,
          duration: theme.transitions.duration.enteringScreen
        }),
        marginLeft: `${drawerWidth}px`
      })
    })
  );

  const DrawerHeader = styled('div')(({ theme }) => ({
    display: 'flex',
    alignItems: 'center',
    padding: theme.spacing(0, 1),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
    justifyContent: 'flex-end'
  }));

  const [open, setOpen] = useState(false);

  return (
    <BackgroundBox>
      <Header open={open} setOpen={setOpen} DrawerHeader={DrawerHeader} drawerWidth={drawerWidth} />
      <SideBar open={open} drawerWidth={drawerWidth} setOpen={setOpen} />
      <Main open={open}>
        <Outlet />
      </Main>
    </BackgroundBox>
  );
};

export default MainLayout;

字符串
要在出口中呈现的示例页面:

//react
import { React, useState, useEffect } from 'react';

//mui
import { Typography } from '@mui/material';

//Project Imports
import { ContentCard } from '../../components/core/ContentCard';
import { gridSpacing } from '../../configuration/config';

// ==============================|| SAMPLE PAGE ||============================== //

const SamplePage1 = () => {
  const [data, setData] = useState('');
  useEffect(() => {
    const dataFetch = async () => {
      const data = await (await fetch('/api/sampleFunction1')).text();
      setData(data);
    };
    dataFetch();
  }, []);

  const cardSx = {
    margin: gridSpacing
  };

  return (
    <ContentCard title={'Sample Page One'} cardSX={cardSx}>
      <Typography variant="body1">
        This is the first sample page, the server responded with: {data}
      </Typography>
    </ContentCard>
  );
};

export default SamplePage1;

eanckbw9

eanckbw91#

您需要将Main移出MainLayout的主体。
否则,每次MainLayout重新呈现时(即当抽屉被切换时),Main都会重新创建,树中它下面的所有内容都会重新挂载(而不仅仅是重新呈现)。

// move Main up here
  const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(
    ({ theme, open }) => ({
      flexGrow: 1,
      padding: theme.spacing(3),
      transition: theme.transitions.create('margin', {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen
      }),
      marginLeft: 0,
      ...(open && {
        transition: theme.transitions.create('margin', {
          easing: theme.transitions.easing.easeOut,
          duration: theme.transitions.duration.enteringScreen
        }),
        marginLeft: `${drawerWidth}px`
      })
    })
  );

const MainLayout = () => {
  const drawerWidth = 240;

  const DrawerHeader = styled('div')(({ theme }) => ({
    display: 'flex',
    alignItems: 'center',
    padding: theme.spacing(0, 1),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
    justifyContent: 'flex-end'
  }));

  const [open, setOpen] = useState(false);

  return (
    <BackgroundBox>
      <Header open={open} setOpen={setOpen} DrawerHeader={DrawerHeader} drawerWidth={drawerWidth} />
      <SideBar open={open} drawerWidth={drawerWidth} setOpen={setOpen} />
      <Main open={open}>
        <Outlet />
      </Main>
    </BackgroundBox>
  );
};

字符串
当你这样做的时候,为了提高效率,把DrawerHeader也移到外面。
永远不要在另一个组件的函数体内声明组件。
这里有一个相关的SO答案:https://stackoverflow.com/a/59776934/954940,尽管我不会称之为dupe。

相关问题