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

React中如何监听容器子元素数量变化并解决ref取值报错问题

问题根因

你遇到的报错和状态不同步问题来自三个核心错误:

  1. 首次渲染时useRef创建的ref对象current属性默认值为undefined,你在useEffect依赖数组中直接访问container.current.children.length,此时ref还未绑定到DOM节点,直接读取属性就会抛出Cannot read properties of undefined (reading 'children')错误。
  2. React的useEffect依赖对比机制只能响应React可控的state、props变化,DOM节点的children.length是原生DOM属性,它的变动不会触发React重渲染和依赖检查,哪怕写在依赖数组里也无法监听到子节点数量变动,必然出现状态和实际值不同步的问题。
  3. 你调用setItems时存入的是子元素数量(数字类型),后续却读取items.length,数字本身没有length属性,逻辑本身存在错误,这也是items.length !== children.length问题的直接诱因。
实现方案

方案1:直接从React数据源获取长度(优先推荐)

你的子元素是通过children.map渲染生成的,子元素数量完全由传入的children属性决定,完全不需要操作DOM读取长度,从根源规避ref空值、监听失效问题:

const container = useRef();
// 初始值设为0,避免初始渲染时值为undefined
const [itemsCount, setItemsCount] = useState(0);

useEffect(() => {
  setItemsCount(children.length);
}, [children]);

return(
  <div ref={container}>
    {children.map(item => <Item key={item.id}/>)}
  </div>
)

这种写法完全遵循React数据驱动的设计逻辑,没有额外DOM操作,状态同步最稳定,性能最好。

方案2:需要监听原生DOM变动时使用MutationObserver

如果容器内的子元素可能被第三方脚本、原生DOM API直接修改(不受React渲染逻辑控制),使用浏览器原生的MutationObserver监听DOM子节点变化,不要依赖useEffect监听DOM属性:

const container = useRef();
const [itemsCount, setItemsCount] = useState(0);

useEffect(() => {
  const targetDom = container.current;
  if (!targetDom) return;

  // 初始化时先同步一次长度
  setItemsCount(targetDom.children.length);

  // 创建DOM变动监听器
  const observer = new MutationObserver(() => {
    setItemsCount(targetDom.children.length);
  });

  // 配置监听规则:仅监听直接子节点的增删
  observer.observe(targetDom, {
    childList: true,
    subtree: false // 不需要监听深层节点变动时保持关闭,减少性能消耗
  });

  // 组件卸载时断开监听,避免内存泄漏
  return () => observer.disconnect();
}, []); // 空依赖即可,仅在组件挂载时绑定一次监听

return(
  <div ref={container}>
    {children.map(item => <Item key={item.id}/>)}
  </div>
)

注意:不要把container.current或其下属DOM属性写入useEffect依赖数组,ref的current属性变动不会触发组件重渲染,写在依赖中没有实际作用,反而容易引发空值报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:27:16