使用react-router-dom时如何避免“无法给功能组件提供引用”?

JGl*_*son 7 reactjs react-router material-ui

我有以下内容(使用Material UI)...

import React from "react";
import { NavLink } from "react-router-dom";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
function LinkTab(link){
    return <Tab component={NavLink}
        to={link.link}
        label={link.label}
        value={link.link}
        key={link.link}
    />;
}
Run Code Online (Sandbox Code Playgroud)

在新版本中,这会导致以下警告...

警告:不能为功能组件提供参考。尝试访问此引用将失败。您是要使用React.forwardRef()吗?

检查的渲染方法ForwardRef。在NavLink中(由ForwardRef创建)

我尝试更改为...

function LinkTab(link){
    // See https://material-ui.com/guides/composition/#caveat-with-refs
    const MyLink = React.forwardRef((props, ref) => <NavLink {...props} ref={ref} />);
    return <Tab component={MyLink}
        to={link.link}
        label={link.label}
        value={link.link}
        key={link.link}
    />;
}
Run Code Online (Sandbox Code Playgroud)

但是我仍然得到警告。我该如何解决这个问题?

Has*_*alp 18

给它作为innerRef,

// Client.js
<Input innerRef={inputRef} />
Run Code Online (Sandbox Code Playgroud)

将其用作ref.

// Input.js
const Input = ({ innerRef }) => {
  return (
    <div>
      <input ref={innerRef} />
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

  • 就这么简单——我发现这是最容易理解的。 (2认同)
  • 如果这有效,为什么存在“forwardRef”? (2认同)
  • 巫术!就像将其从“ref”更改为“innerRef”一样简单 (2认同)

Nei*_*lDA 16

如果您发现无法添加自定义ref道具或forwardRef组件,我有一个技巧仍然可以为您的功能组件获取 ref 对象。

假设您想将 ref 添加到自定义功能组件,例如:

 const ref = useRef();

 //throws error as Button is a functional component without ref prop
 return <Button ref={ref}>Hi</Button>;
Run Code Online (Sandbox Code Playgroud)

您可以将其包装在通用 html 元素中并ref对其进行设置。

 const ref = useRef();

 // This ref works. To get button html element inside div, you can do 
 const buttonRef = ref.current && ref.current.children[0];
 return (
  <div ref={ref}>
   <Button>Hi</Button>
  </div>
 );
Run Code Online (Sandbox Code Playgroud)

当然,相应地管理状态以及您想要使用buttonRef对象的位置。


kes*_*lal 13

在我们的例子中,我们将 SVG 组件(站点的徽标)直接传递给 NextJS 的链接组件,该组件经过了一些定制,并且我们收到了这样的错误。

使用 SVG 并“导致”问题的标头组件。

import Logo from '_public/logos/logo.svg'
import Link from '_components/link/Link'

const Header = () => (
  <div className={s.headerLogo}>
    <Link href={'/'}>
      <Logo /> 
    </Link>
  </div>
)
Run Code Online (Sandbox Code Playgroud)

控制台上的错误消息

Function components cannot be given refs. Attempts to access this ref will fail.
Did you mean to use React.forwardRef()?
Run Code Online (Sandbox Code Playgroud)

定制链接组件

import NextLink from 'next/link'
import { forwardRef } from 'react'

const Link = ({ href, shallow, replace, children, passHref, className }, ref) => {
  return href ? (
    <NextLink
      href={href}
      passHref={passHref}
      scroll={false}
      shallow={shallow}
      replace={replace}
      prefetch={false}
      className={className}
    >
      {children}
    </NextLink>
  ) : (
    <div className={className}>{children}</div>
  )
}

export default forwardRef(Link)

Run Code Online (Sandbox Code Playgroud)

现在我们确保我们在自定义的链接组件中使用了forwardRef,但我们仍然遇到该错误。

为了解决这个问题,我将 SVG 元素的包装器定位更改为:poof:

const Header = () => (
  <Link href={'/'}>
    <div className={s.headerLogo}>
      <Logo />
    </div>
 </Link>
)
Run Code Online (Sandbox Code Playgroud)

  • 创建自定义下一个链接组件时遇到了类似的问题,该组件基本上是样式文本组件的包装器 - 通过在我的包装组件周围添加一个片段而不是 div 来解决它。 (2认同)

Moh*_*sim 9

forwardRef要修复此警告,您应该使用本博客中提到的函数很好地包装自定义组件

    const AppTextField =(props) {return(/*your component*/)}
Run Code Online (Sandbox Code Playgroud)

将上面的代码改为

const AppTextField = forwardRef((props,ref) {return(/*your component*/)}
Run Code Online (Sandbox Code Playgroud)


Ina*_*man 8

嗨,您可以使用refs而不是ref

    <InputText
        label="Phone Number"
        name="phoneNumber"
        refs={register({ required: true })}
        error={errors.phoneNumber ? true : false}
        icon={MailIcon}
   />
Run Code Online (Sandbox Code Playgroud)

  • 你好。您能解释一下 ref 和 refs 之间的区别吗?我查看了 React 文档,但找不到任何对 refs={} (复数)的引用。这实际上对我有用,但我想了解它如何在功能组件上工作。谢谢。 (13认同)
  • 这并不是说它是专门参考的。只是“ref”这个道具是一个特殊的道具(就像“key”一样)。您可以将其传递为“foo”而不是“refs”,它也可以工作。 (5认同)
  • 我发现自己也在质疑 `refs` 是否是一个特殊的 prop,所以我选择了 `innerRef` 只是因为它更清楚它在做什么。 (2认同)

eps*_*lon 5

NavLinkfrom react-router是一个功能组件,它是Link的特殊版本,它innerRef为此目的提供了一个支持。

// required for react-router-dom < 6.0.0
// see https://github.com/ReactTraining/react-router/issues/6056#issuecomment-435524678
const MyLink = React.forwardRef((props, ref) => <NavLink innerRef={ref} {...props} />);
Run Code Online (Sandbox Code Playgroud)

你也可以已经搜寻过的文档了react-router,导致你https://material-ui.com/getting-started/faq/#how-do-i-use-react-router其链接到https://开头材料- ui.com/components/buttons/#third-party-routing-library。最后一个链接提供了一个有效的示例,并说明了这在React-router v6中将如何改变

  • 如果你根本不使用react-router怎么办?你如何使用带有相同警告的forwardRef? (2认同)