React中useState引发内存溢出与重复渲染问题求助
React时钟组件渲染次数剧增、内存占用过高的解决方案
问题根源
你的代码核心问题在于useEffect的依赖数组包含了time:每次setTime更新state后,useEffect都会重新执行,而每次执行又会创建一个新的setInterval,且旧的定时器从未被清理。这就导致每秒都会新增一批定时器,每个定时器都触发setTime,进而引发更多渲染,最终形成几何级增长的渲染次数和持续飙升的内存占用。
修正后的代码
import React, { useState, useEffect } from "react"; import classes from "./Clock.module.css"; const ClockCurrent = (props) => { const [time, setTime] = useState(new Date()); useEffect(() => { // 组件挂载时仅创建一次定时器 const timerId = setInterval(() => { setTime(new Date()); }, 1000); // 组件卸载时清除定时器,避免内存泄漏 return () => clearInterval(timerId); }, []); // 空依赖数组,确保useEffect只执行一次 // 直接生成格式化时间,轻量操作无需useMemo const currentTime = time.toLocaleTimeString("ru", { timeZone: "Europe/Moscow", }); return ( <div className={classes.Clock}> <h2>{currentTime}</h2> </div> ); }; export default ClockCurrent;
关键改动说明
- 空依赖数组:将useEffect的依赖改为
[],确保组件首次挂载时仅执行一次,只会创建一个定时器,从根源避免了重复创建定时器的问题。 - 定时器清理:在useEffect中返回清理函数,组件卸载时自动清除定时器,防止无用定时器占用内存。
- 简化逻辑:移除了多余的
useMemo——toLocaleTimeString是轻量的字符串格式化操作,缓存它带来的收益远小于代码复杂度,完全可以直接调用。 - 移除无效依赖:定时器回调中直接创建新的
Date对象,不需要依赖外部的time变量,避免了不必要的state依赖触发重复执行。
补充说明
你之前尝试的useMemo无效,是因为问题的核心不在渲染阶段的计算开销,而在于定时器的重复创建导致的state更新风暴。只要解决了定时器重复创建的问题,渲染次数和内存占用就会恢复正常。
内容的提问来源于stack exchange,提问作者Delshi
相关产品推荐
相关产品推荐

