You need to enable JavaScript to run this app. 使用MUI与styled-components做响应式开发时出现过多重渲染如何解决
优惠活动
大模型
产品
解决方案
定价
更多

使用MUI与styled-components做响应式开发时出现过多重渲染如何解决

问题根因

你的代码产生无限重渲染的核心原因是:在组件渲染的主流程中直接调用了setfontSize状态更新方法。React中调用状态更新方法会触发组件重新渲染,而重渲染后又会再次执行if (isMedium)判断并调用setfontSize,由此形成无限循环,导致重渲染次数过多。
另外你当前场景下fontSize完全是由isMedium的返回值派生的,根本不需要单独声明为状态,完全可以通过计算直接得到,这也是你走弯路的核心原因。

修复方案

直接删除无用的useState声明和条件更新逻辑,直接计算fontSize的值即可,修正后的完整代码如下:

import React 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'));
  // 直接计算fontSize,无需状态
  const fontSize = isMedium ? '45px' : '20px';
 
  return (
    <div>
      <AppBar
        position="static"
        elevation={0}
        style={{
          background: 'white',
        }}
      >
        <Toolbar>
          <img className={classes.logo} src={Logojsam} alt="Bosch Logo" />
          {!isMobile && (
            <section className={classes.rightToolbar}>
              <MyButton fontSize={fontSize} component={Link} to="/">
                About Us
              </MyButton>
              <MyButton fontSize={fontSize} component={Link} to="/community">
                Community
              </MyButton>
              <MyButton fontSize={fontSize} component={Link} to="/community">
                Activities
              </MyButton>
              <MyButton fontSize={fontSize} component={Link} to="/gallery">
                Gallery
              </MyButton>
              <MyButton fontSize={fontSize} component={Link} to="/contact-us">
                Contact Us
              </MyButton>
              <MyButton fontSize={fontSize} component={Link} to="/contact-us">
                En
              </MyButton>
            </section>
          )}
        </Toolbar>
      </AppBar>
    </div>
  );
};

export default Navbar;

可选优化方案

如果你不想在js层做判断,也可以直接在styled-components中使用MUI的断点能力实现纯CSS级别的响应式,连useMediaQuery和fontSize传参都可以省略,代码更简洁:

const MyButton = styled(Button)(({ theme }) => ({
  padding: '0 14px',
  fontSize: '20px',
  [theme.breakpoints.down('md')]: {
    fontSize: '45px'
  }
}));

使用这个方案的话,你就不需要在Navbar组件里计算和传递fontSize属性了,所有响应式逻辑都收敛在样式定义中。

内容的提问来源于stack exchange,提问作者SpicyyRiice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 02:36:08