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

React函数未按预期返回图片:视口切换不更新图片问题

React响应式图片切换问题修复

我导入了两张图片(IMG和IMG2),预期视口宽度小于600px时显示IMG,大于等于600px时显示IMG2。编写了检查视口宽度的函数返回对应图片,但函数始终只返回第一张图片IMG,即使视口宽度超过600px也不会切换到IMG2。注:我可以通过媒体查询设置display:none解决,但想了解React的实现方式。


现有React组件代码

import IMG from '../../assets/image-product-mobile.jpg'
import IMG2 from '../../assets/image-product-desktop.jpg'

const ProductImage = () => {
  function displayImage(){
    let vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
    console.log(vw);
    if(vw < 600) {
     console.log(vw + "is smaller than 600");
     return (<img src={IMG} alt="" />);
    } else {
     console.log(vw + "is bigger than 600");
     return (<img src={IMG2} alt="" />);
    }
}
  return (
    <div className='container-img'>
      {displayImage()}
    </div>
  )
}

export default ProductImage

现有CSS代码

.container-img img {
    height: 15rem;
    width: 100%;
    background: white;
    border-radius: 0.8rem 0.8rem 0 0;
}

.container-img {
   
}

 /* -----------------for bigger phones------------------- */

@media screen and (min-width: 390px) {
    .container-img img {
        height: 20rem;
    }
}

问题原因

当前代码仅在组件首次渲染时执行displayImage函数计算视口宽度,窗口大小变化时不会触发组件重渲染,所以图片不会更新。

React实现方案

使用React的useState存储当前视口宽度,useEffect监听窗口resize事件更新状态,让组件根据状态变化重新渲染图片。

修改后的组件代码

import { useState, useEffect } from 'react';
import IMG from '../../assets/image-product-mobile.jpg'
import IMG2 from '../../assets/image-product-desktop.jpg'

const ProductImage = () => {
  // 存储当前视口宽度
  const [viewportWidth, setViewportWidth] = useState(
    Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
  );

  // 监听窗口resize事件,更新视口宽度
  useEffect(() => {
    const handleResize = () => {
      const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
      setViewportWidth(width);
    };

    window.addEventListener('resize', handleResize);
    // 组件卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // 根据当前视口宽度返回对应图片
  return (
    <div className='container-img'>
      {viewportWidth < 600 ? 
        <img src={IMG} alt="产品移动端图片" /> : 
        <img src={IMG2} alt="产品桌面端图片" />
      }
    </div>
  )
}

export default ProductImage

更高效的优化方案(使用matchMedia)

如果想避免频繁触发resize事件,可以使用浏览器的matchMediaAPI,它能直接监听媒体查询的变化,性能更优:

import { useState, useEffect } from 'react';
import IMG from '../../assets/image-product-mobile.jpg'
import IMG2 from '../../assets/image-product-desktop.jpg'

const ProductImage = () => {
  const [isMobile, setIsMobile] = useState(window.matchMedia('(max-width: 599px)').matches);

  useEffect(() => {
    const mediaQuery = window.matchMedia('(max-width: 599px)');
    const handleMediaChange = (e) => setIsMobile(e.matches);

    mediaQuery.addEventListener('change', handleMediaChange);
    return () => mediaQuery.removeEventListener('change', handleMediaChange);
  }, []);

  return (
    <div className='container-img'>
      {isMobile ? 
        <img src={IMG} alt="产品移动端图片" /> : 
        <img src={IMG2} alt="产品桌面端图片" />
      }
    </div>
  )
}

export default ProductImage

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:01:11