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

IT技术 reactjs react-router material-ui
2021-04-10 05:17:54

我有以下内容(使用 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}
    />;
}

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

警告:不能为函数组件提供引用。尝试访问此引用将失败。你的意思是使用 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}
    />;
}

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

6个回答

NavLinkfromreact-router是一个函数组件,它是Link的专用版本,innerRef为此目的公开了一个prop。

// 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} />);

您还可以搜索我们的文档,react-router这些文档会引导您到https://mui.com/getting-started/faq/#how-do-i-use-react-router链接到https://mui.com/组件/按钮/#third-party-routing-library最后一个链接提供了一个工作示例,并解释了这在 react-router v6 中可能发生的变化

当我们从 react-router-hash-link 获得哈希链接时怎么样?
2021-05-26 05:17:54
此链接帮助我解决问题 [ blog.jscrambler.com/...
2021-06-04 05:17:54
如果您根本不使用 react-router 呢?您如何使用具有相同警告的 forwardRef?
2021-06-13 05:17:54

给它作为innerRef

// Client.js
<Input innerRef={inputRef} />

将其用作ref.

// Input.js
const Input = ({ innerRef }) => {
  return (
    <div>
      <input ref={innerRef} />
    </div>
  )
}
巫术!那么容易,因为对其进行更改ref,以innerRef
2021-05-25 05:17:54
如果这有效,为什么forwardRef存在?
2021-05-31 05:17:54
@Hasan 是认真的吗?这实际上有效,并且不涉及其他答案中提到的任何重大变化。
2021-06-07 05:17:54
就这么简单 - 我发现这是最容易理解的。
2021-06-13 05:17:54

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

    <InputText
        label="Phone Number"
        name="phoneNumber"
        refs={register({ required: true })}
        error={errors.phoneNumber ? true : false}
        icon={MailIcon}
   />
正如@FilipeValente 所说,它不是任何特定的参考。它只是充当道具,
2021-05-27 05:17:54
你好。你能解释一下 ref 和 refs 之间的区别吗?我查看了 React 文档,但找不到任何对 refs={} (复数)的引用。这实际上对我有用,但想了解它如何在功能组件上工作。谢谢你。
2021-06-04 05:17:54
并不是说它是专门的 refs。只是道具“ref”是一个特殊的道具(就像“key”一样)。您可以将它作为“foo”而不是“refs”传递,它也可以工作。
2021-06-07 05:17:54
我发现自己也在质疑它是否refs是一个特殊的道具,所以我选择了innerRef只是因为它更清楚它的作用。
2021-06-07 05:17:54

在我们的例子中,我们将一个 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>
)

控制台上的错误消息

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

自定义链接组件

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)

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

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

const Header = () => (
  <Link href={'/'}>
    <div className={s.headerLogo}>
      <Logo />
    </div>
 </Link>
)
在创建自定义下一个链接组件时遇到了类似的问题,该组件基本上是样式文本组件的包装器 - 通过在我包装的组件周围添加一个片段而不是 div 来解决它。
2021-06-06 05:17:54

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

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

 const ref = useRef();

 //throws error as Button is a functional component without ref prop
 return <Button ref={ref}>Hi</Button>;

您可以将其包装在通用 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>
 );

当然,相应地管理状态以及您想在何处使用 buttonRef 对象。