使用 react-router-dom 时如何避免“功能组件不能被赋予 refs”?
Posted
技术标签:
【中文标题】使用 react-router-dom 时如何避免“功能组件不能被赋予 refs”?【英文标题】:How do I avoid 'Function components cannot be given refs' when using react-router-dom? 【发布时间】:2019-10-22 09:25:06 【问题描述】:我有以下(使用 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
/>;
在新版本中,这会导致以下警告...
警告:函数组件不能被赋予 refs。尝试访问 这个裁判会失败。你的意思是使用 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
/>;
但我仍然收到警告。我该如何解决这个问题?
【问题讨论】:
【参考方案1】:来自react-router
的NavLink
是一个函数组件,它是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 />);
您还可以在我们的文档中搜索 react-router
,这会将您引导至链接到 https://mui.com/components/buttons/#third-party-routing-library 的 https://mui.com/getting-started/faq/#how-do-i-use-react-router。最后一个链接提供了一个工作示例,并解释了这在 react-router v6 中可能会如何变化
【讨论】:
如果我们有来自 react-router-hash-link 的哈希链接呢? 如果你根本不使用 react-router 怎么样?你如何使用 forwardRef 和同样的警告? 这个链接帮助我解决问题 [blog.jscrambler.com/…【参考方案2】:您好,您可以使用 refs 代替 ref
<InputText
label="Phone Number"
name="phoneNumber"
refs=register( required: true )
error=errors.phoneNumber ? true : false
icon=MailIcon
/>
【讨论】:
你好。你能解释一下 ref 和 refs 之间的区别吗?我查看了 React 文档,但找不到任何对 refs=(复数)的引用。这对我很有用,但想了解它在功能组件上的工作原理。谢谢。 并不是特指refs。只是道具“ref”是一个特殊的道具(就像“key”一样)。您可以将其传递为“foo”而不是“refs”,它也可以工作。 正如@FilipeValente 所说,它不是任何特定的参考。它只是充当道具, 我发现自己也在质疑refs
是否是一个特殊的道具,所以我选择了 innerRef
只是因为它的作用更清晰一些。【参考方案3】:
只要给它innerRef
,
// Client.js
<Input innerRef=inputRef />
将其用作ref
。
// Input.js
const Input = ( innerRef ) =>
return (
<div>
<input ref=innerRef />
</div>
)
【讨论】:
就这么简单——我发现这是最容易理解的。 @Hasan 认真的吗?这实际上有效,并且没有像其他答案中提到的那样涉及任何重大变化。 如果可行,为什么forwardRef
存在?
魔法!就像将它从 ref
更改为 innerRef
一样简单【参考方案4】:
const renderItem = ( item, index ) =>
return (
<>
<Item
key=item.Id
item=item
index=index
/>
</>
);
;
使用 Fragment 解决 React.forwardRef()?警告
【讨论】:
【参考方案5】:如果您发现无法将自定义 ref
属性或 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 对象。
【讨论】:
【参考方案6】:要解决此警告,您应该使用 forwardRef
函数包装您的自定义组件,正如 blog 中提到的那样非常好
const AppTextField =(props) return(/*your component*/)
以下代码改为
const AppTextField = forwardRef((props,ref) return(/*your component*/)
【讨论】:
【参考方案7】:在我们的例子中,我们将一个 SVG 组件(网站的徽标)直接传递给 NextJS 的 Link Component,这有点定制,我们遇到了这样的错误。
使用 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元素的wrapper定位改成了this和:poof:
const Header = () => (
<Link href='/'>
<div className=s.headerLogo>
<Logo />
</div>
</Link>
)
【讨论】:
在创建自定义下一个链接组件时遇到了类似的问题,该组件基本上是围绕样式文本组件的包装器 - 通过在包装组件周围添加片段而不是 div 解决了这个问题。以上是关于使用 react-router-dom 时如何避免“功能组件不能被赋予 refs”?的主要内容,如果未能解决你的问题,请参考以下文章
使用 yarn 工作区和 react-router-dom v6 时如何正确继承上下文?
如何配置tomcat 7以在react中使用react-router-dom?
如何使用 react-router-dom v6 中的历史对象重定向到特定页面
如何在 React.js 中使用 react-router-dom 保持 App() 级别状态不重置?