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

React中使用setInterval+useState报错:Failed to execute 'removeChild' on 'Node'

问题原因及修复方案

你的代码出现「Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node」错误,核心原因有两个:

  1. useEffect未设置依赖数组:组件每次渲染(包括seconds更新后)都会新建一个定时器,多个定时器同时运行,频繁修改状态导致DOM更新逻辑混乱,触发节点移除错误。
  2. 闭包陷阱:定时器回调里的seconds是创建定时器时捕获的旧值,比如初始值30,即便setSeconds更新了状态,后续定时器依然用旧值计算,导致状态更新异常,进一步加剧DOM冲突。

修复方案一:添加依赖数组+函数式更新

给useEffect指定依赖[seconds],确保seconds变化时清理旧定时器并创建新的;同时用函数式更新setSeconds,确保每次拿到最新状态值:

const [seconds, setSeconds] = useState(30);

useEffect(() => {
  // 倒计时结束就不再创建定时器
  if (seconds <= 0) return;
  
  const myInterval = setInterval(() => {
    setSeconds(prevSeconds => prevSeconds - 1);
  }, 1000);

  return () => clearInterval(myInterval);
}, [seconds]);

修复方案二:单次挂载定时器+useRef保存ID

如果不想每次seconds变化都重建定时器,可以用useRef保存定时器ID,仅在组件挂载时创建一次定时器,通过函数式更新处理状态:

import { useState, useEffect, useRef } from 'react';

const [seconds, setSeconds] = useState(30);
const intervalRef = useRef(null);

useEffect(() => {
  intervalRef.current = setInterval(() => {
    setSeconds(prev => {
      if (prev <= 0) {
        clearInterval(intervalRef.current);
        return 0;
      }
      return prev - 1;
    });
  }, 1000);

  return () => clearInterval(intervalRef.current);
}, []);

这两种方案都能避免多个定时器同时运行,解决闭包导致的状态更新异常,从而消除DOM操作错误。

内容的提问来源于stack exchange,提问作者Nick Jonas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:15:04