You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何在屏幕尺寸变化时自动添加/移除className?

在React中根据屏幕尺寸动态切换预定义className的方案

我完全懂你的困扰——CSS媒体查询确实没办法直接帮你动态添加/移除这类预定义类,毕竟它是纯样式层面的规则,没法直接操作DOM的类名。下面给你几个React项目里常用且靠谱的解决方案:

方案1:监听window.resize事件 + useState状态管理

这是最直接易懂的方式,核心思路是通过监听窗口尺寸变化,用状态记录当前屏幕是否符合断点条件,再根据状态动态拼接类名。

步骤如下:

  1. 在组件中声明状态来存储屏幕尺寸判断结果:
    import { useState, useEffect } from 'react';
    
    function YourComponent() {
      // 这里以"屏幕宽度小于768px时添加bold类"为例
      const [shouldAddBoldClass, setShouldAddBoldClass] = useState(false);
    
  2. 使用useEffect监听窗口resize事件,同时在组件挂载时初始化判断:
    useEffect(() => {
        // 定义判断屏幕尺寸的函数
        const checkScreenSize = () => {
          setShouldAddBoldClass(window.innerWidth < 768);
        };
    
        // 组件挂载时先执行一次,避免初始状态不对
        checkScreenSize();
        // 添加resize事件监听
        window.addEventListener('resize', checkScreenSize);
    
        // 组件卸载时移除监听,防止内存泄漏
        return () => window.removeEventListener('resize', checkScreenSize);
      }, []);
    
  3. 在组件元素上根据状态动态添加类:
    return (
        <div className={`your-base-class ${shouldAddBoldClass ? 'bold' : ''}`}>
          你的内容
        </div>
      );
    }
    

如果需要处理多个断点(比如xs/sm/md/lg),可以把状态改成存储当前屏幕类型,比如:

const [screenType, setScreenType] = useState('md');

const checkScreenSize = () => {
  const width = window.innerWidth;
  if (width < 576) setScreenType('xs');
  else if (width < 768) setScreenType('sm');
  else if (width < 992) setScreenType('md');
  else setScreenType('lg');
};

然后对应不同类:

<div className={`base-class ${screenType === 'sm' ? 'bold' : ''} ${screenType === 'xs' ? 'italic' : ''}`}>...</div>

方案2:封装useMediaQuery自定义Hook(更优雅高效)

如果你需要在多个组件中复用这个逻辑,推荐封装一个基于浏览器matchMediaAPI的自定义Hook,它比直接监听resize更高效——只有当媒体查询的结果变化时才会触发状态更新,而不是每次窗口拖动都执行判断。

先封装Hook:

import { useState, useEffect } from 'react';

const useMediaQuery = (mediaQuery) => {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    // 创建媒体查询对象
    const mediaList = window.matchMedia(mediaQuery);
    
    // 初始化状态
    setMatches(mediaList.matches);

    // 定义查询结果变化时的回调
    const handleChange = (e) => setMatches(e.matches);
    
    // 添加监听
    mediaList.addEventListener('change', handleChange);

    // 清理函数
    return () => mediaList.removeEventListener('change', handleChange);
  }, [mediaQuery]);

  return matches;
};

然后在组件中使用:

function YourComponent() {
  // 判断屏幕是否小于768px
  const isSmallScreen = useMediaQuery('(max-width: 767px)');

  return (
    <div className={`base-class ${isSmallScreen ? 'bold' : ''}`}>
      你的内容
    </div>
  );
}

优化小技巧:用classnames简化类名拼接

如果需要切换多个类,手动拼接字符串容易出错,推荐使用classnames库来简化逻辑:

  1. 先安装库:
npm install classnames
# 或者 yarn add classnames
  1. 在组件中使用:
import classNames from 'classnames';

function YourComponent() {
  const isSmallScreen = useMediaQuery('(max-width: 767px)');
  const isLargeScreen = useMediaQuery('(min-width: 992px)');

  const containerClass = classNames(
    'base-class',
    { bold: isSmallScreen },
    { 'text-large': isLargeScreen }
  );

  return <div className={containerClass}>你的内容</div>;
}

注意事项

  • 如果你的项目是服务端渲染(SSR),要注意window对象在服务端不存在,需要加判断:typeof window !== 'undefined',比如在初始化状态或监听事件前先判断;
  • 所有事件监听都要在组件卸载时清理,避免内存泄漏;
  • 可以根据你的实际需求调整断点数值和对应的类名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:25:34