【问题标题】:React - access component library's child DOMReact - 访问组件库的子 DOM
【发布时间】:2021-04-16 17:23:12
【问题描述】:

我正在使用一个组件库,它呈现嵌套在多个 div 元素中的 input 字段

<ComponentLibrary />

这个组件库渲染一棵类似于下面的树:

<div className={outerDiv}>
  <div>
    <input type="text" />  // This the element I'm trying to access
  </div>
</div>

我构建了一个自定义组件,它包装了ComponentLibrary,如下所示:

<MyCustomComponent>
  <ComponentLibrary />
</MyCustomComponent>

我无权修改组件库,但我需要访问它在我的组件中的 input 字段。

const MyCustomComponent = (props) => {
  const inputRef = useRef();

  return (
    {React.cloneElement(props.children, {
      ref: inputRef // This ofcourse references the 'outerDiv'
    }}
  );
}

一些可能的相关说明,当我console.log(props.children)。虽然组件是 react 元素,但类型是前向引用。

> children:
  $$typeof: Symbol(react.element)
  ref: null
  > type: {$$typeof: Symbol(react.forward_ref)}

下面是我做了一些尝试:

{React.Children.map(props.children, child => {
   console.log(child) // Only logs the Component element. No reference of DOM nodes
}

我得到的最接近的是使用我在上面第四个代码块中创建的inputRef

console.log(inputRef.current)
// Logs `outerDiv` element

console.log(inputRef.current.children[0]?.children[1]?.children[1])
// Returns the right element, but an absolute mess. Is this my best solution?

【问题讨论】:

  • 你使用的组件库是什么?
  • @BasvanderLinden 我正在使用我公司的一个团队构建的内部组件库,该团队独立于我的工作。
  • ComponentLibrary的文档接口是什么?最好使用它而不是使用 React 内部结构,这种方式可能会在下次 ComponentLibrary 的实现更新时中断。

标签: javascript reactjs


【解决方案1】:

我可能在这里理解错了,但通过阅读您的问题,我认为ComponentLibrary 看起来像这样:

const ComponentLibrary = React.forwardRef((props, ref) => (
  <div ref={ref}>
    <div>
      <input type="text" />
    </div>
  </div>
));

我假设这是因为 props.childrentype 属性的值为

$$typeof: Symbol(react.forward_ref)

在复制您的 MyCustomComponent 设置时

const MyCustomComponent = (props) => {
  const inputRef = useRef();

  useEffect(() => {
    console.log(inputRef.current); 
  });

  return React.cloneElement(props.children, {
    ref: inputRef,
  });
};

inputRef.current 注销以下元素:

<div>
  <div>
    <input type="text" />
  </div>
</div>

您可以使用children 属性来查找子元素并将其链接起来以最终获得输入元素,就像您在示例中所做的那样,但您也可以使用Element.querySelector 并通过其属性和/或定位元素输入。

例如:

console.log(inputRef.current.querySelector('input[type="text"]'));

【讨论】:

  • 更好的解决方案。谢谢你。老实说,我什至没有想过这样做!
  • 所以,由于 ComponentLibrary 是一个 forwardedRef。有没有更好/首选的方式来访问它或它的孩子,而不是props.children
  • 另外,感谢您对我的包容。我意识到这是很多帖子,对于单行解决方案。但是,您分解各种代码块并重申我提供的信息或为我提出的问题提供上下文,这非常有帮助。为你的耐心和细节喝彩
  • 我不确定是否有更好的方法。如果您在函数参数({children}) 中使用解构而不是(props),则可以使用children,但这是一个非常微不足道的变化。您也可以直接在MyCustomComponent 内渲染ComponentLibrary,而不使用道具并直接附加参考。与使用 children 相比,您在包装其他类似类型的组件方面会失去一些灵活性。有关从子元素获取 dom 节点的方法的概述,您可以查看...
  • ...this
猜你喜欢
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 2016-10-12
  • 2018-09-11
  • 2018-02-09
  • 2014-08-19
  • 1970-01-01
  • 2021-11-03
相关资源
最近更新 更多