Понимание: Предупреждение: функциональным компонентам нельзя давать ссылки

Я знаю, что ссылки используются для прямого доступа к элементам DOM без изменения состояния. Я читал, что нельзя давать ссылки на функциональные компоненты, потому что у них нет состояния.

Ссылки не могут быть прикреплены к функциональным компонентам. Хотя мы можем определить ссылки и прикрепить их либо к элементам DOM, либо к компонентам класса. Суть в том, что у функциональных компонентов нет экземпляров, поэтому вы не можете ссылаться на них.

взято из: https://blog.logrocket.com/cleaning-up-the-dom-with-forwardref-in-react/

Я все еще не понимаю.

Я использую Tooltipкомпонент из Ant 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?

Почему тогда, если я пройду ref к Button компонент он все еще выдает предупреждение?

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

Если я пройду antd Buttonпрямо в детстве это работает. Но это потому, что я полагаю, что кнопка antd имеет состояние, следовательно, у нее могут быть ссылки.

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

2 ответа

В качестве состояния предупреждения вы не можете назначить ссылки функциональному компоненту без использования forwardRef

Чтобы иметь доступ к ссылкам любого компонента, требуется, чтобы был создан экземпляр компонента, а экземпляр создавался только для компонентов класса, в то время как функциональные компоненты вызываются или вызываются

Начиная с версии v16.8.0, React представил API под названием useRef, который позволяет вам создавать ссылки в функциональных компонентах, которые можно использовать на узлах HTML, компонентах классов или функциональных компонентах, заключенных в forwardRef

Чтобы добиться того же поведения, которое доступно в компонентах класса с помощью ref, вы можете использовать forwardRef с useImperativeHandle крючок, чтобы предоставить родительским элементам определенные функции или состояния в функциональном компоненте

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

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

  )
}

Не путайте, во-первых, это не связано с проблемой функциональных или классовых компонентов, значит, вы можете использовать ref для обоих, response 16+ имеет крючок useRef так что вы также можете использовать ref для функциональных компонентов,

Ответь на твой вопрос, antd Buttonимеет свой собственный ref, поэтому он опускает ref, переданный родительским компонентом, в вашем случаеTooltip вот почему вы не видите никаких предупреждений об этом, но когда вы использовали свой собственный компонент, в этот раз вы должны ref прошло Tooltip.

И все же вы не хотите использовать React.forwordRefзатем просто игнорируйте его, передавая реквизиты вашему компоненту. но тогда вы не получаете привилегий какой-либо функции, предоставляемойantd контролируемые компоненты

Другие вопросы по тегам