【问题标题】:Detect when child ref is changing检测子参考何时发生变化
【发布时间】:2020-09-09 14:26:07
【问题描述】:

我有以下问题:

有一个子组件接受从父组件传下来的 ref:

const ChildComp = React.forwardRef((props, ref) => <div ref={ref} />)

父组件创建一个 ref 数组并将数组中的一个 ref 分配给其中一个子组件:


const ParentComp = () => {
 const items = [1,2,3]
 const refs = items.map(() => React.createRef()) 

 React.useEffect(() => {
  console.log(refs);
 }, [refs])

 return <div>{items.map((item, index) => <ChildComp ref={refs[index]>)}</div>
}

但是,当我在useEffect 中输出 refs 数组的状态时,它仅在父级挂载时输出一次,此时 ref.current 值仍为空,因为尚未挂载子级。

我希望能够拥有一个 ref 数组,其中每个 ref 属于一个孩子,如上图所示。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    这是一个有效的 Codesandbox:https://codesandbox.io/s/currying-leaf-tpibl?file=/src/App.tsx

    我稍微修改了你的例子:

    • 仅使用功能组件,因为字符串引用(来自createRef)不应与它们一起使用
    • 使用callback refs而不是创建它们,这将对节点的变化做出反应

    重要的是

    refProp={(node) =&gt; (itemsRef.current[index] = node)},

    这将基于通过ChildComp 的回调引用填充itemsRef 数组。

    ChildComp

    const ChildComp = ({
      number,
      refProp
    }: {
      number: number;
      refProp: (node: HTMLDivElement) => void;
    }) => {
      // simulate internal child state for demonstration
      const [childState, setChildState] = useState(0);
    
      useEffect(() => setChildState(number * 2), [number]);
    
      return (
        <div ref={refProp}>
          <p>
            State from child no. {number}: {childState}
          </p>
        </div>
      );
    };
    

    ParentComp

    const ParentComp = () => {
      const [items] = useState([1, 2, 3]);
      // you can access the elements with itemsRef.current[n]
      const itemsRef = useRef<Array<HTMLDivElement | null>>([]);
    
      useEffect(() => {
        // create initial refs array, will be filled through callback ref
        itemsRef.current = itemsRef.current.slice(0, items.length);
      }, [items]);
    
      useEffect(() => {
        // this logs the three <div>s of the childs
        console.log(itemsRef);
      }, [itemsRef]);
    
      return (
        <>
          <p>Hi from parent!</p>
          {items.map((_, index) => (
            <ChildComp
              key={index}
              number={index + 1}
              // will be called by React when they're changing
              refProp={(node) => (itemsRef.current[index] = node)}
            />
          ))}
        </>
      );
    };
    

    【讨论】:

      【解决方案2】:

      也许refs 数组中的每个引用都在变化,但数组本身没有变化。这就是为什么 useEffect 没有再次运行的原因。

      你可以试试:

      React.useEffect(() => {
        console.log(refs);
       }, [refs[0].current])
      

      【讨论】:

      • 这也只会在装载时触发一次。
      猜你喜欢
      • 2016-12-28
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多