首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ref.current在React.forwardRef中的应用

ref.current在React.forwardRef中的应用
EN

Stack Overflow用户
提问于 2020-06-06 22:22:58
回答 4查看 15.6K关注 0票数 30

这里的代码箱

我试图使用父组件中的ref来侦听子组件中的某些ref事件,其中ref使用React.forwardRef连接到子组件。然而,当我引用ref.current时,我在子组件中收到了一个令人毛骨悚然的抱怨,它说:

属性'current‘在类型'Ref’上不存在。属性“current”不存在于类型上(例如: HTMLDivElement) => void‘

如何在React.forwardRef组件中引用ref?谢谢。

index.tsx:

代码语言:javascript
运行
复制
import * as React from "react";
import ReactDOM from "react-dom";

const Component = React.forwardRef<HTMLDivElement>((props, ref) => {
  React.useEffect(() => {
    const node = ref.current;
    const listen = (): void => console.log("foo");

    if (node) {
      node.addEventListener("mouseover", listen);
    }
    return () => {
      node.removeEventListener("mouseover", listen);
    };
  }, [ref]);

  return <div ref={ref}>Hello World</div>;
});

export default Component;

const App: React.FC = () => {
  const sampleRef = React.useRef<HTMLDivElement>(null);

  return <Component ref={sampleRef} />;
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-06-06 22:49:00

Refs不一定是具有current属性的对象。它们也可以是函数。因此,类型错误指出,您可能会被传递给后者之一。您需要编写代码,以便它可以同时处理这两种变体。

这可能有点棘手,但它是可行的。我们的效果不能回到传递给我们的函数上,因为这个函数可以做任何事情,而且编写时没有考虑到我们的useEffect。因此,我们需要创建自己的ref,我称之为myRef。

现在有两个参考文献:一个是传入的,另一个是本地的。要填充这两种元素,我们需要自己使用refs的函数形式,在这个函数中,我们可以将div元素分配给这两个参考文献:

代码语言:javascript
运行
复制
const Component = React.forwardRef<HTMLDivElement>((props, ref) => {
  const myRef = useRef<HTMLDivElement | null>(null);
  React.useEffect(() => {
    const node = myRef.current;
    const listen = (): void => console.log("foo");

    if (node) {
      node.addEventListener("mouseover", listen);
    }
    return () => {
      node.removeEventListener("mouseover", listen);
    };
  }, [ref]);

  return (
    <div ref={(node) => {
      myRef.current = node;
      if (typeof ref === 'function') {
        ref(node);
      } else if (ref) {
        ref.current = node;
      }
    }}>Hello World</div>
  );
});
票数 59
EN

Stack Overflow用户

发布于 2022-06-08 18:25:11

详述@Nicholas答复:

代码语言:javascript
运行
复制
import React, { MutableRefObject, Ref, useEffect } from "react";
import { TextInput } from "react-native";

type CustomTextInputProps = {};

export const CustomTextInput = React.forwardRef<
  TextInput,
  CustomTextInputProps
>((props, ref) => {
  const localRef = React.useRef<TextInput | null>(null);

  useEffect(() => {
    // using the local ref
    localRef.current?.focus();
  }, []);

  return <TextInput {...props} ref={assignRefs(localRef, ref)} />;
});

const assignRefs = <T extends unknown>(...refs: Ref<T | null>[]) => {
  return (node: T | null) => {
    refs.forEach((r) => {
      if (typeof r === "function") {
        r(node);
      } else if (r) {
        (r as MutableRefObject<T | null>).current = node;
      }
    });
  };
};
票数 6
EN

Stack Overflow用户

发布于 2022-09-16 17:30:42

我四处搜索,因为这是另一个钩子,如useForwardRef很好的候选。这是提议,https://github.com/facebook/react/issues/24722

我自己也试过,对此效果很好。

代码语言:javascript
运行
复制
const InputField = React.forwardRef<HTMLInputElement, InputFieldProps>(
  (props, ref) => {
   const inputRef = useForwardRef<HTMLInputElement>(ref);
   const onLabelClick = () => {
    inputRef.current?.focus();
  };

  return <input ref={inputRef} />
 );

当然,这基本上是相同的代码在最初的答案,但写成一个钩子。

代码语言:javascript
运行
复制
const useForwardRef = <T,>(
  ref: ForwardedRef<T>,
  initialValue: any = null
) => {
  const targetRef = useRef<T>(initialValue);

  useEffect(() => {
    if (!ref) return;

    if (typeof ref === 'function') {
      ref(targetRef.current);
    } else {
      ref.current = targetRef.current;
    }
  }, [ref]);

  return targetRef;
};

注意:钩子的名字是有争议的,它可以被命名为useCopyRefuseBorrowRef什么的。为了简单起见,因为它是为forwardRef创建的,所以我们将其命名为useForwardRef,但实际上它与转发无关。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62238716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档