useEffect依赖window.innerWidth不触发回调及日期更新问题求助
问题分析与解决方案
你的代码核心问题有三个:
- 全局变量无法触发React重渲染:你用了全局的
currentDate,React组件只会响应内部状态/ props的变化,全局变量更新后组件根本不知道,所以依赖数组里的currentDate.getDay()这些值不会变化,useEffect自然不会重新执行。 - 没有监听窗口resize事件:
window.innerWidth不会自动触发React的依赖检测,必须手动监听resize事件,把窗口宽度存在状态里,才能让useEffect感知到变化。 - setInterval只更新全局变量,没触发组件更新:定时器里只是替换了全局的
currentDate,但没有调用setState,组件不会重新渲染,日期自然不会更新。
修正后的代码
import { useState, useEffect } from "react" export default function LocalDate() { // 用组件内部状态管理当前日期和窗口宽度 const [currentDate, setCurrentDate] = useState(new Date()) const [windowWidth, setWindowWidth] = useState(window.innerWidth) const [date, setDate] = useState("") useEffect(() => { // 格式化日期的逻辑 const options = windowWidth < 735 ? { weekday: "short", day: "numeric", month: "short" } : { weekday: "long", day: "numeric", month: "long" } let formattedDate = currentDate.toLocaleDateString("en-US", options) let parts = formattedDate.split(" ") let formattedDateSwapped = `${parts[0]} ${parts[2]} ${parts[1]}` setDate(formattedDateSwapped) }, [currentDate, windowWidth]) // 依赖正确的状态变量 useEffect(() => { // 定时器:每2秒更新当前日期状态 const interval = setInterval(() => { setCurrentDate(new Date()) }, 2000) // 监听窗口resize事件,更新宽度状态 const handleResize = () => { setWindowWidth(window.innerWidth) } window.addEventListener("resize", handleResize) // 清理函数:组件卸载时清除定时器和监听 return () => { clearInterval(interval) window.removeEventListener("resize", handleResize) } }, []) // 这个useEffect只在组件挂载时执行一次 return ( <h2 id="date">{date}</h2> ) }
关键改动说明
- 把
currentDate改成组件内部的useState状态,每次调用setCurrentDate都会触发组件重渲染,useEffect也会跟着执行。 - 新增
windowWidth状态,通过resize事件监听更新,确保窗口大小变化时useEffect能感知到。 - 拆分了两个
useEffect:一个负责日期和宽度变化时的格式化逻辑,另一个负责初始化定时器和resize监听,职责更清晰。 - 移除了全局变量
formattedDate,避免不必要的全局污染。
内容的提问来源于stack exchange,提问作者Finlay Foulds
相关产品推荐
相关产品推荐

