使用 MUI 和样式化组件重新渲染的次数过多

Posted

技术标签:

【中文标题】使用 MUI 和样式化组件重新渲染的次数过多【英文标题】:Too many re-renders with MUI and styled component 【发布时间】:2021-07-29 08:17:12 【问题描述】:

您好,我尝试渲染一个使用 MUI(Material-UI) 和 styled-component 的页面。我使用了 useTheme 和 useMediaQuery 来使我的 web 应用程序响应。我尝试让我的应用程序响应并更改字体大小(如果它是小型设备)

我的问题是根据控制台渲染太多

我知道问题在于 useState 的 if else 语句,但我不知道还有什么其他选择可以让这成为可能

下面是代码:

import React,  useState  from 'react';
import  makeStyles  from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import  Link  from 'react-router-dom';
import Logojsam from '../../assets/icons/logo-jsam.png';

import useMediaQuery from '@material-ui/core/useMediaQuery';
import  useTheme  from '@material-ui/core/styles';

import styled from 'styled-components';
const useStyles = makeStyles((theme) => (
  rightToolbar: 
    marginLeft: 'auto',
    marginRight: -10,
  ,
  logo: 
    width: 185,
    height: 185,
    padding: '20px 0px',
  ,
));

const MyButton = styled(Button)(
  padding: '0 14px',
  fontSize: (props) => props.fontSize || '20px',
);



const Navbar = () => 
  const classes = useStyles();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  const isMedium = useMediaQuery(theme.breakpoints.down('md'));

  const [fontSize, setfontSize] = useState();
 
  if (isMedium)
  
    setfontSize('45px');
  
    return (
      <div>
        <AppBar
          position="static"
          elevation=0
          style=
            background: 'white',
          
        >
          <Toolbar>
            <img className=classes.logo src=Logojsam  />
            !isMobile && (
              <section className=classes.rightToolbar>
                <MyButton fontSize=fontSize component=Link to="/">
                  About Us
                </MyButton>
                <MyButton component=Link to="/community">
                  Community
                </MyButton>
                <MyButton component=Link to="/community">
                  Activities
                </MyButton>
                <MyButton component=Link to="/gallery">
                  Gallery
                </MyButton>
                <MyButton component=Link to="/contact-us">
                  Contact Us
                </MyButton>
                <MyButton component=Link to="/contact-us">
                  En
                </MyButton>
              </section>
            )
          </Toolbar>
        </AppBar>
      </div>
    );
;

export default Navbar;



谢谢

【问题讨论】:

您在组件的主体中调用setfontSize。这意味着,如果isMedium 为真,则调用setfontSize('45px');,触发重新渲染,再次运行函数,再次调用setfontSize('45px');,触发重新渲染,再次运行函数等. 你应该把状态更改放在useEffect 中,所以它只在挂载和isMedium 更改时运行 好吧,如果我理解的话,如果“渲染过多”有问题,我需要使用useEffect吗? 嗯,这不是您每次遇到这个问题时的解决方案,这只是这种情况下的解决方案 【参考方案1】:

useEffect() Hook 让您可以在函数组件中执行副作用。如 cmets 所述。通过 Jayce444,当您在组件主体内调用 setfontSize() 时,它会触发重新渲染。将其放入 useEffect 中,仅在 isMedium 更改时重新运行

import React,  useState, useEffect  from 'react';

然后

useEffect(() => 
  if (isMedium)
    setfontSize('45px')
  
, [isMedium]); // Only re-run the effect if isMedium changes

【讨论】:

以上是关于使用 MUI 和样式化组件重新渲染的次数过多的主要内容,如果未能解决你的问题,请参考以下文章

样式化的 MUI 无法在 typescript 中将组件道具传递给 Typography

在样式化组件中设置 React 组件道具

样式化组件中的条件渲染

样式化的组件输入失去焦点 onChange

使用 React Hooks 重新渲染的次数过多

React 限制渲染次数以防止无限循环...重新渲染次数过多