理解:警告:不能给函数组件提供引用

IT技术 javascript reactjs ref react-forwardref
2021-04-08 06:12:18

我知道 refs 用于直接访问 DOM 元素而不改变状态。我读到无法为功能组件提供引用,因为它们没有状态。

Refs 不能附加到函数组件。虽然,我们可以定义 refs 并将它们附加到 DOM 元素或类组件。底线是——函数组件没有实例,所以你不能引用它们。

取自:https : //blog.logrocket.com/cleaning-up-the-dom-with-forwardref-in-react/

我还是不明白。

我正在使用TooltipAnt Design ( https://ant.design/components/tooltip/ ) 中的Button组件组件和自定义CircleButton组件。

鉴于以下 JSX:

<Tooltip placement="left" title={"Lock slot"}>
  <CircleButton onClick={() => execute(client.close)} icon={<LockOutlined />} disabled={loading} />
</Tooltip>

还有我的 CircleButton 组件。像这样使用,它会产生警告

const CircleButton = (props) => // gives the warning
  <Button shape="circle" size="small" style={{ marginRight: "8px" }} {...props} />

警告:不能为函数组件提供引用。尝试访问此引用将失败。你的意思是使用 React.forwardRef() 吗?

请注意,尽管有警告,但一切都按预期工作。

如果我按如下方式编辑它,它会正常工作,为什么?

const CircleButton = forwardRef((props, ref) => // doesn't give the warning
  <div ref={ref}>
    <Button shape="circle" size="small" style={{ marginRight: "8px" }} {...props} />
  </div>)

请问div组件有一个状态?我不明白。是在forwardRef做一些魔法并为 div 元素创建一个状态吗?

为什么如果我将 传递refButton组件它仍然会发出警告?

const CircleButton = forwardRef((props, ref) => // gives the warning
  <Button ref={ref} shape="circle" size="small" style={{ marginRight: "8px" }} {...props} />)

如果我antd Button小时候直接通过,它会起作用。但这是因为我认为 antd 按钮有一个状态,因此它可以有 refs。

<Tooltip placement="left" title={"Lock slot"}> // doesn't give the warning
  <Button shape="circle" size="small" style={{ marginRight: "8px" }} />
</Tooltip>
2个回答

作为警告状态,您不能在不使用 forwardRef 的情况下将 refs 分配给功能组件

为了访问任何组件的 refs,它需要创建一个组件的实例,并且只为类组件创建一个实例,而调用或调用功能组件

从 v16.8.0 开始,React 引入了一个名为 useRef 的 API,它允许您在功能组件中创建 refs 也可以在 HTML 节点、类组件或用 forwardRef 包装的功能组件上使用

要使用 ref 实现类组件中可用的相同行为,您可以使用forwardRefwith useImperativeHandlehook 将功能组件中的某些函数或状态公开给父级

const CircleButton = forwardRef((props, ref) => {
  const someFunction = () =>{}
  useImperativeHandle(ref, () => ({
     someFunc
  }));

  return (
    <div>
        <Button shape="circle" size="small" style={{ marginRight: "8px" }} {...props} />
   </div>

  )
}

不要混淆,首先这与功能或类组件问题无关,这意味着您可以将 ref 用于两者,react 16+ 具有钩子,useRef因此您也可以将 ref 用于功能组件,

回答你的问题,antd Button有他们自己的 ref,所以它在你的情况下省略了父组件传递的 ref Tooltip,为什么你没有看到任何警告,但是当你使用自己的组件时,你必须接受refpass by Tooltip

而且,您仍然不想使用React.forwordRef然后在将props传递给您的组件时简单地忽略它。但是随后您将无法获得antd受控组件提供的某些功能的特权