【问题标题】:React: How to get Parent component's width from Child component with hooks?React:如何使用钩子从子组件中获取父组件的宽度?
【发布时间】:2021-10-26 20:30:05
【问题描述】:

假设我有 2 个组件,ParentChild。我需要一种方法来访问ParentsChild 中的宽度,并且还需要useEffect 在此宽度发生变化时触发一些代码。

当我在parent 上使用引用并将其作为道具传递给child 并尝试通过parentRef.current.clientWidth 访问它时,尝试使用useRef 给我一个类似于Cannot access clientWidth property of undefined 的错误.

片段

const parentRef = useRef();

return(
<Parent ref={parentRef}>
<Child parentRef={parentRef}/>
</Parent>
)

我该怎么办?

【问题讨论】:

  • 你是如何传递 ref 的?
  • @e.a.添加在原始答案中。
  • 对不起。我的意思是你如何在子组件中使用它。你在使用 forwardRef 吗?因为你不能像普通道具一样消耗它
  • @e.a.我将它用作普通道具。 forwardedRef 是什么?你能给我举个例子吗?
  • 我在答案中发布了向您展示代码。它会解决你的问题

标签: html reactjs react-hooks


【解决方案1】:

为了访问子组件中的 ref,您需要将组件包装在 React.forwardRef 函数中,并使用 ref 作为第二个参数,而不是在 props 对象中,所以:

const Child = React.forwardRef((props, ref) => {})

& 在您的父母中,您将拥有:

<Child ref={parentRef}/>

你可以阅读更多关于它here

【讨论】:

  • 所以,如果我理解正确的话,我会创建一个父容器,比如&lt;div ref={parentRef}&gt;,其中parentRef 是用const parentRef = useRef() 创建的,然后导出像export default forwardRef((props, ref) =&gt; {}) 这样的子组件,然后通过ref.current 获取父母的句柄,对吗?
  • 是的。除了出口部分。组件的名称在哪里? :) 您可以使用命名函数并说export default forwardRef(function Child (props, ref) {}),或者像大多数人习惯的那样,为匿名函数定义一个变量,例如`const Child = forwardRef((props, ref) => {})`,然后@ 987654330@在底部。
【解决方案2】:

在父级中创建状态 使函数取值并改变状态 在道具中将功能从父母传递给孩子 在具有宽度值的子进程中执行函数

【讨论】:

  • 你能澄清一下你说的话吗?
  • 好的,我现在知道了!
【解决方案3】:

您可以使用ResizeObserver api 来监听Parent 上附加的调整大小事件

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

const Child = ({ width = 0 }) => {

  useEffect(() => {
    // listen for the change in width
    // do something here when the width changes
  }, [width]);

  return <p> Parent Div Size: {width} </p>;
};

const Parent = () => {
  const divRef = useRef(null);
  const [width, setWidth] = useState(0);

  useEffect(() => {
    const resizeObserver = new ResizeObserver((entries) => {
      // this callback gets executed whenever the size changes
      // when size changes get the width and update the state
      // so that the Child component can access the updated width
      for (let entry of entries) {
        if (entry.contentRect) {
          setWidth(entry.contentRect.width);
        }
      }
    });

    // register the observer for the div
    resizeObserver.observe(divRef.current);

    // unregister the observer
    return () => resizeObserver.unobserve(divRef.current);
  }, []);

  return (
    <div
      ref={divRef}
      style={{
        textAlign: "center",
        height: "100px",
        border: "solid 1px"
      }}
    >
      <Child width={width} />
    </div>
  );
};

export default Parent;

Working Sandbox

参考

Resize Observer API

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多