如何聆听儿童的长度变化反应?

发布于 2025-02-07 03:42:07 字数 453 浏览 1 评论 0原文

我有一个代码:

const container = useRef();
const [items, setItems] = useState();

useEffect(()=>{
  setItems(container.current.children.length);
},[container.current, container.current.children.length])

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

items.length!== childrent。 >项目相应。但是我会发现无法读取未定义的属性(阅读“孩子”)我知道为什么会发生这种情况,但是我不知道如何处理它。

I have a code:

const container = useRef();
const [items, setItems] = useState();

useEffect(()=>{
  setItems(container.current.children.length);
},[container.current, container.current.children.length])

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

items.length !== children.length so I want to listen to container.current.children.length size and when it changes, change items accordingly. But I get error that Cannot read properties of undefined (reading 'children') I understand why it's happening, but I don't know how to work around it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巨坚强 2025-02-14 03:42:07

首先,您绝对不应将useref值放在depenty数组中,因为如果值已更改,它不会触发使用效应回调。

您在这里有两个选择:

  1. 创建一个自定义组件,您可以手动观察孩子的长度。
function ChildrenObserver({ children }) {
  const lastCount = useRef(getChildrenCount());
  const currentCount = getChildrenCount();

  function getChildrenCount() {
    return React.Children.toArray(children).length;
  }

  if (lastCount.current !== currentCount) {
    lastCount.current = currentCount;
    console.log("Children length changed to", lastCount.current);
  }

  return children;
}

function App() {
  const [items, setItems] = useState(0);

  return (
    <>
      <button onClick={() => setItems((i) => i + 1)}>Add child</button>
      <ol>
        <ChildrenObserver>
          {Array.from({ length: items }).map((item) => (
            <li key={item}>Item {item}</li>
          ))}
        </ChildrenObserver>
      </ol>
    </>
  );
}
  1. 创建一个突变操作器,以聆听DOM更改。
function App() {
  const [items, setItems] = useState(0);

  const setRef = useCallback((ref) => {
    const observer = new MutationObserver((mutationsList) => {
      for (let mutation of mutationsList) {
        if (mutation.type === "childList") {
          console.log("Children length changed to", ref.children.length);
        }
      }
    });

    observer.observe(ref, { childList: true });
  }, []);

  return (
    <>
      <button onClick={() => setItems((i) => i + 1)}>Add child</button>
      <ol ref={setRef}>
        {Array.from({ length: items }).map((item) => (
          <li key={item}>Item {item}</li>
        ))}
      </ol>
    </>
  );
}

First of all, you should never put a useRef value inside a depedency array, as it won't trigger the useEffect callback to run if the value has changed.

You have two options here:

  1. Create a custom component in which you can manually observe the children length.
function ChildrenObserver({ children }) {
  const lastCount = useRef(getChildrenCount());
  const currentCount = getChildrenCount();

  function getChildrenCount() {
    return React.Children.toArray(children).length;
  }

  if (lastCount.current !== currentCount) {
    lastCount.current = currentCount;
    console.log("Children length changed to", lastCount.current);
  }

  return children;
}

function App() {
  const [items, setItems] = useState(0);

  return (
    <>
      <button onClick={() => setItems((i) => i + 1)}>Add child</button>
      <ol>
        <ChildrenObserver>
          {Array.from({ length: items }).map((item) => (
            <li key={item}>Item {item}</li>
          ))}
        </ChildrenObserver>
      </ol>
    </>
  );
}
  1. Create a MutationObserver that listens for dom changes.
function App() {
  const [items, setItems] = useState(0);

  const setRef = useCallback((ref) => {
    const observer = new MutationObserver((mutationsList) => {
      for (let mutation of mutationsList) {
        if (mutation.type === "childList") {
          console.log("Children length changed to", ref.children.length);
        }
      }
    });

    observer.observe(ref, { childList: true });
  }, []);

  return (
    <>
      <button onClick={() => setItems((i) => i + 1)}>Add child</button>
      <ol ref={setRef}>
        {Array.from({ length: items }).map((item) => (
          <li key={item}>Item {item}</li>
        ))}
      </ol>
    </>
  );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文