Children 不通过 Ref 更新道具更改

Children do not update on props change via Ref

我有以下 React 组件:

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

function Child({ containerWidth }) {
  console.log("CHILD", containerWidth);
  return <div>My parent's width is {containerWidth}px</div>;
}

export default function App() {
  const containerRef = useRef(null);
  const [containerWidth, setContainerWidth] = useState(null);
  const [width, setWidth] = useState(400);

  console.log("PARENT", containerWidth);

  useEffect(() => {
    if (containerRef.current) {
      setContainerWidth(containerRef.current.clientWidth);
    }
  }, [containerRef]);

  const handleWidth = () => setWidth(1000);

  console.log("width", width);

  return (
    <div ref={containerRef} style={{ width: width }}>
      <Child containerWidth={containerWidth} />
      <button onClick={handleWidth}>change my width</button>
    </div>
  );
}

我需要 children 始终知道并在宽度发生变化时重新渲染。即使我们单击按钮更改宽度,此 ref 的值也保持不变。

我试过使用 useCallback 调用函数但没有成功,因为 ref 永远不会改变。

 const getChild = useCallback(
    () => <Child containerWidth={containerWidth} />,
    [containerWidth]
  );

(.....)

  return (
    <div ref={containerRef} style={{ width: width }}>
      {getChild()}
      <button onClick={handleWidth}>change my width</button>
    </div>
  );

它确实有效,但只有一次,因为您正在检查 ref 是否存在。一旦它存在,它将不再触发 useEffect 逻辑。您可以使用 useEffect 中的事件侦听器来管理它。我刚刚为您创建了一个示例演示。这是工作代码和框 https://codesandbox.io/embed/wild-flower-ytv2b3?fontsize=14&hidenavigation=1&theme=dark

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

function Child({ containerWidth }) {
  console.log("CHILD", containerWidth);
  return <div>My parent's width is {containerWidth}px</div>;
}

export default function App() {
  const containerRef = useRef(null);
  const [containerWidth, setContainerWidth] = useState(window.innerWidth);
  const [width, setWidth] = useState(400);

  console.log("PARENT", containerWidth);

  const handleResize = () => {
    setContainerWidth(window.innerWidth);
  };

  useEffect(() => {
    window.addEventListener("resize", handleResize, false);
  }, []);

  const handleWidth = () => setWidth(containerWidth);

  console.log("width", width);

  return (
    <div ref={containerRef} style={{ width: width }}>
      <Child containerWidth={width} />
      <button onClick={handleWidth}>change my width</button>
    </div>
  );
}