ReactforwardRef - 访问组件内和父级中的引用

发布于 2025-01-11 03:04:45 字数 773 浏览 0 评论 0原文

我需要访问组件内文本区域的引用。在组件内,这很简单:

const MyComponent = () => {
  const inputRef = useRef();

  return <textarea ref={inputRef} />
}

现在 ref 在 MyComponent 中可用,我可以将它用于一些内部逻辑。

在某些情况下,我也需要从父组件访问引用。在这种情况下,我可以使用forwardRef:

const MyComponent = React.forwardRef((props, ref) => {
  return <textarea ref={ref} />
})

// In some parent
const MyParent = () => {
  const inputRefFromParent = useRef();
  return <MyComponent ref={inputRefFromParent} />
}

现在我可以从父组件访问 textarea 的 ref,并将其用于父组件内的逻辑。

我发现自己处于这样的情况:我需要使用 MyComponent 中的引用执行一些内部逻辑,但我可能还需要从 MyParent 获取该引用。我该怎么做?

I need to access the ref to a textarea inside a component. Within the component, its easy enough:

const MyComponent = () => {
  const inputRef = useRef();

  return <textarea ref={inputRef} />
}

Now the ref is available within MyComponent and I can use it for some internal logic.

There are cases where I need to access the ref from the parent component as well. In that case, I can use forwardRef:

const MyComponent = React.forwardRef((props, ref) => {
  return <textarea ref={ref} />
})

// In some parent
const MyParent = () => {
  const inputRefFromParent = useRef();
  return <MyComponent ref={inputRefFromParent} />
}

Now I can access to ref of the textarea from the parent component, and use it for logic within the parent component.

I find myself in a situation where I need to do some internal logic with the ref within MyComponent, but I may also need to get that ref from MyParent. How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

笑看君怀她人 2025-01-18 03:04:45

您可以在 MyComponent 中保留 ref 并使用 useImperativeHandle 挂钩,使用从 MyParent 传递的 ref

尝试如下所示。它将文本区域中的焦点方法公开给父级。您还可以通过访问 textAreaRef 执行任何其他内部操作。

import { useRef, forwardRef, useImperativeHandle } from "react";

const MyComponent = forwardRef((props, ref) => {
  const textAreaRef = useRef();

  // all the functions or values you can expose here
  useImperativeHandle(ref, () => ({
    focus: () => {
      textAreaRef.current.focus();
    }
  }));

  const internalFunction = () => {
    // access textAreaRef
  };

  return <textarea ref={textAreaRef} />;
});

// In some parent
const MyParent = () => {
  const inputRefFromParent = useRef();

  // you can call inputRefFromParent.current.focus(); in this compoenent
  return <MyComponent ref={inputRefFromParent} />;
};

You can keep a ref in the MyComponent and expose what you would need in the parent component using useImperativeHandle hook using the ref passed from the MyParent.

Try like below. It exposes the focus method in the textarea to parent. And you can do any other internal things with the access to textAreaRef.

import { useRef, forwardRef, useImperativeHandle } from "react";

const MyComponent = forwardRef((props, ref) => {
  const textAreaRef = useRef();

  // all the functions or values you can expose here
  useImperativeHandle(ref, () => ({
    focus: () => {
      textAreaRef.current.focus();
    }
  }));

  const internalFunction = () => {
    // access textAreaRef
  };

  return <textarea ref={textAreaRef} />;
});

// In some parent
const MyParent = () => {
  const inputRefFromParent = useRef();

  // you can call inputRefFromParent.current.focus(); in this compoenent
  return <MyComponent ref={inputRefFromParent} />;
};
半世晨晓 2025-01-18 03:04:45

除了阿米拉的回答之外,我还找到了另一种方法,即使用 ref 回调

const MyComponent = React.forwardRef((props, parentRef) => {
  const localRef = useRef();
  return <textarea ref={ref => {
    parentRef.current = ref;
    localRef.current = ref;
  }} />
})

因此回调 ref 对 textarea 的 ref 保持更细粒度的控制,并简单地将其值分配给本地引用和父引用。

In addition to Amila's answer, I found another way to do it, by using a ref callback:

const MyComponent = React.forwardRef((props, parentRef) => {
  const localRef = useRef();
  return <textarea ref={ref => {
    parentRef.current = ref;
    localRef.current = ref;
  }} />
})

So the callback ref keeps finer grain control of the ref to the textarea, and simply assigns its value to both the local ref and the parent ref.

[浮城] 2025-01-18 03:04:45

对我有用的是:

export const MyComponent: FC<Props> = forwardRef<HTMLInputElement, Props>(
  function myComponent(
    { /* ... */    }: Props,
    forwardedRef
  ) {
    const innerRef = useRef<HTMLInputElement | null>(null);
    return (
    <div>
      <input ref={(instance: HTMLInputElement) => {
              innerRef.current = instance;
              if (typeof forwardedRef === "function") forwardedRef(instance);
              else if (forwardedRef !== null) forwardedRef.current = instance;
            }} />
    </div>
    )
  }
)

What's working for me is:

export const MyComponent: FC<Props> = forwardRef<HTMLInputElement, Props>(
  function myComponent(
    { /* ... */    }: Props,
    forwardedRef
  ) {
    const innerRef = useRef<HTMLInputElement | null>(null);
    return (
    <div>
      <input ref={(instance: HTMLInputElement) => {
              innerRef.current = instance;
              if (typeof forwardedRef === "function") forwardedRef(instance);
              else if (forwardedRef !== null) forwardedRef.current = instance;
            }} />
    </div>
    )
  }
)
离鸿 2025-01-18 03:04:45

要在转发引用的同时访问引用:

  • 将组件内部创建的引用附加到元素。
  • 调用外部引用上的 useImperativeHandle 挂钩(正在转发to)并传递一个返回内部引用的 current 属性的函数,该值将被设置为外部引用的 current 属性。这将整个参考暴露给消费者,而不是选择性地挑选某些属性。
import { forwardRef, useImperativeHandle, useRef } from 'react';
const MyComponent = forwardRef((props, outerRef) => {
    const innerRef = useRef(null);
    useImperativeHandle(outerRef, () => innerRef.current, []);
    // remember to list any dependencies of the function that returns the ref value, similar to useEffect
    return <textarea ref={innerRef} />
});

或者使用 TypeScript:

import { forwardRef, useImperativeHandle, useRef } from 'react';
const MyComponent = forwardRef<HTMLTextAreaElement>((props, outerRef) => {
    const innerRef = useRef<HTMLTextAreaElement>(null);
    useImperativeHandle(outerRef, () => innerRef.current!, []);
    return <textarea ref={innerRef} />
});

To access a ref while also forwarding it:

  • Attach a ref created inside the component to the element.
  • Call the useImperativeHandle hook on the outer ref (which is being forwarded to) and pass a function that returns the current property of the inner ref, which is the value that will be set to the current property of the outer ref. This exposes the entire ref to consumers rather than selectively picking certain properties.
import { forwardRef, useImperativeHandle, useRef } from 'react';
const MyComponent = forwardRef((props, outerRef) => {
    const innerRef = useRef(null);
    useImperativeHandle(outerRef, () => innerRef.current, []);
    // remember to list any dependencies of the function that returns the ref value, similar to useEffect
    return <textarea ref={innerRef} />
});

Or with TypeScript:

import { forwardRef, useImperativeHandle, useRef } from 'react';
const MyComponent = forwardRef<HTMLTextAreaElement>((props, outerRef) => {
    const innerRef = useRef<HTMLTextAreaElement>(null);
    useImperativeHandle(outerRef, () => innerRef.current!, []);
    return <textarea ref={innerRef} />
});
恏ㄋ傷疤忘ㄋ疼 2025-01-18 03:04:45

您还可以执行以下操作:

const MyComponent = React.forwardRef((props, externalRef) => {
    const internalRef = useRef<HTMLElement>();
    const ref = useMemo(
        () => externalRef || internalRef,
        [externalRef, internalRef]
    ) as React.MutableRefObject<HTMLElement>;
    
    return <textarea ref={ref} />
})

You could do also the following:

const MyComponent = React.forwardRef((props, externalRef) => {
    const internalRef = useRef<HTMLElement>();
    const ref = useMemo(
        () => externalRef || internalRef,
        [externalRef, internalRef]
    ) as React.MutableRefObject<HTMLElement>;
    
    return <textarea ref={ref} />
})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文