【问题标题】:What's the correct way to use useRef and forwardRef together?一起使用 useRef 和 forwardRef 的正确方法是什么?
【发布时间】:2021-09-10 17:09:15
【问题描述】:

我有两个组件:AppChild。我使用 useRef 钩子来获取 Child 组件中的 DOM 元素并对其进行一些处理。

我还使用React.forwardRef API 将refApp 组件传递给Child 组件。

App.tsx:

import { useRef } from "react";
import Child from "./Child";

export default function App() {
  const ref = useRef(null);
  console.log("App ref: ", ref);
  return (
    <div className="App">
      <Child ref={ref} />
    </div>
  );
}

Child.ts:

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

export default React.forwardRef((props, ref) => {
  const innerRef = useRef<HTMLDivElement>(null);
  const divElement = ref || innerRef; // TSC throw error here.
  useEffect(() => {
    if (divElement.current) {
      console.log("clientWidth: ", divElement.current.clientWidth);
      // do something with divElement.current
    }
  }, []);
  return <div ref={divElement}></div>;
});

我不确定使用innerRef 和转发ref 是否像上面一样正确。至少,TSC 会抛出一个错误,这意味着它不允许这样使用它。

键入'((实例:未知) => void) | MutableRefObject' 不可分配给类型 'string | (((实例:HTMLDivElement | null)=> void)|参考对象 |空 |不明确的'。 类型 'MutableRefObject' 不可分配给类型 'string | (((实例:HTMLDivElement | null)=> void)|参考对象 |空 |不明确的'。 类型“MutableRefObject”不可分配给类型“RefObject”。 属性“当前”的类型不兼容。 类型“未知”不可分配给类型“HTMLDivElement |空值'。 类型“未知”不可分配给类型“HTMLDivElement”.ts(2322) index.d.ts(143, 9):预期类型来自属性 'ref',它在此处声明类型为 'DetailedHTMLProps'

我想在App 组件中获得正确的引用,并在子组件中使用这个ref。我该怎么做?

codesandbox

【问题讨论】:

标签: reactjs typescript react-hooks


【解决方案1】:

您可以在很大程度上忽略 TS 错误,因为您没有为 forwardRef 参数提供类型,因此它不知道 ref/innerRef 是等效类型的。

const divElement = ref || innerRef;&lt;div ref={divElement}&gt;&lt;/div&gt;

我不明白这一点 - 你是否希望它直接引用 div 元素,而不管是否给定了 ref ?

无论如何,我认为如果你想让它像这样工作,最好使用useImperativeHandle 钩子,比如useImperativeHandle(ref, () =&gt; innerRef.current);

因此,子组件本身使用innerRef 管理引用,但如果有人确实将引用传递给子组件,它将产生。


export default React.forwardRef((props, ref) => {
  const innerRef = useRef<HTMLDivElement>(null);

  useImperativeHandle(ref, () => innerRef.current);

  useEffect(() => {
    if (innerRef.current) {
      console.log("clientWidth: ", innerRef.current.clientWidth);
    }
  }, []);

  return <div ref={innerRef}></div>;
});

【讨论】:

    猜你喜欢
    • 2020-08-27
    • 2023-04-06
    • 2018-04-10
    • 2013-01-02
    • 1970-01-01
    • 2020-07-10
    • 2020-09-29
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多