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
相关产品推荐
相关产品推荐

