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

替换Redux状态切片属性值时JS堆内存持续增长问题求助

JS堆内存未释放问题原因分析

问题场景

使用CRA+Redux开发内存检测MVP,生产环境(npm run build + serve -s build)运行时内存表现异常:

  • 点击「set data」按钮,JS堆内存增加100MB;
  • 点击「clear」按钮后内存无下降;
  • 三次点击「set data」后内存升至300MB,触发浏览器「Collect garbage」后内存仍保持300MB。
    测试环境:Microsoft Edge 116.0.1938.69

相关代码

JavaScript代码

const { createRoot } = ReactDOM;
const { Fragment, StrictMode, useEffect } = React;
const { createStore } = Redux;
const { Provider, useDispatch, useSelector } = ReactRedux;

function reducer(state = { data: [] }, action) {
  switch (action.type) {
    case 'SET_DATA':
      return { ...state, data: new Array(1000000 * 100).join('a') };
    case 'CLEAR':
      return { ...state, data: [] };
    default:
      return state;
  }
}

const store = createStore(reducer);

const App = () => {
  const dispatch = useDispatch();
  const state = useSelector((state) => state.data);

  console.log({ state });

  useEffect(() => {
    return () => {
      dispatch({ type: 'CLEAR' });
    };
  }, [dispatch]);

  return (
    <div>
      <button onClick={() => dispatch({ type: 'SET_DATA' })}>set data</button>
      <button onClick={() => dispatch({ type: 'CLEAR' })}>clear</button>
    </div>
  );
};

const root = createRoot(document.getElementById("root"));
root.render(<StrictMode><Provider store={store}><App /></Provider></StrictMode>);

HTML代码

<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/redux@4.2.1/dist/redux.js"></script>
<script crossorigin src="https://unpkg.com/react-redux@8.1.2/dist/react-redux.js"></script>

核心原因

  1. 控制台日志持有内存引用
    代码中console.log({ state })会在每次组件渲染时打印状态对象,浏览器控制台默认会持久化保存这些日志的引用。即使Redux状态已清空,包含大字符串的旧状态对象仍被控制台日志持有,无法被垃圾回收机制释放。

  2. Redux状态更新的残留引用
    每次触发SET_DATA时,reducer会生成包含超大字符串的新状态对象。虽然CLEAR动作会将状态重置为空数组,但旧状态对象可能被ReactRedux的内部订阅缓存、或者未完成的渲染周期持有隐性引用,导致内存无法回收。

  3. 浏览器内存缓存策略
    浏览器为减少内存分配/回收的性能开销,会将已释放的内存保留为缓存池,即使手动触发垃圾回收,也不会立即将所有可回收内存归还给系统,表现为内存占用数值无明显下降。


内容的提问来源于stack exchange,提问作者Lin Du

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:08:28