Как избежать «Компоненты функций не могут получить ссылки» при использовании react-router-dom?

У меня есть следующее (используя 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}
    />;
}

В новых версиях это вызывает следующее предупреждение...

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

Check the render method of ForwardRef. in NavLink (created by 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}
    />;
}

Но я все еще получаю предупреждение. Как решить эту проблему?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
89
0
153 828
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Ответ принят как подходящий

NavLink from react-router — это функциональный компонент, представляющий собой специализированную версию Связь, которая предоставляет для этой цели свойство 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/getting-started/faq/#how-do-i-use-react-router, который ссылается на https://mui.com/components/buttons/# третья сторона-маршрутизация-библиотека. В последней ссылке приведен рабочий пример, а также объясняется, как это может измениться в react-router v6.

Как насчет того, когда у нас есть хэш-ссылка от react-router-hash-link?

user7075574 13.02.2020 13:08

как насчет того, если вы вообще не используете реактивный маршрутизатор? как вы используете forwardRef с тем же предупреждением?

Dimitri Kopriwa 29.03.2020 18:36

эта ссылка поможет мне решить проблему [blog.jscrambler.com/…

Mohd Qasim 30.09.2021 15:51

Вы можете использовать судьи вместо ссылка. Это работает только потому, что избегает специального имени пропса ссылка.

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

Привет. Не могли бы вы объяснить разницу между ref и refs? Я просмотрел документацию React, но не смог найти ссылки на refs = {} (множественное число). Это действительно сработало для меня, но я хотел бы понять, как это работает с функциональными компонентами. Спасибо.

user2590243 29.06.2020 21:29

Дело не в том, что это конкретно реф. Просто проп "ref" особенный (так же, как и "key"). Вы можете передать его как «foo» вместо «refs», и это тоже сработает.

Filipe Valente 04.10.2020 16:55

Как сказал @FilipeValente, это не какая-то конкретная ссылка. Он просто выступает в качестве реквизита,

Inamur Rahman 09.10.2020 05:55

Я также обнаружил, что задаюсь вопросом, был ли refs каким-то особым реквизитом, поэтому я выбрал innerRef только потому, что это немного яснее в отношении того, что он делает.

Liam 20.04.2021 13:35

Просто поставьте как innerRef,

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

Используйте его как ref.

// Input.js
const Input = ({ innerRef }) => {
  return (
    <div>
      <input ref = {innerRef} />
    </div>
  )
}

Как бы это ни было просто - я обнаружил, что это легче всего обернуть в голове.

Liam 20.04.2021 13:33

@ Хасан серьезно? Это действительно сработало и не привело к каким-либо существенным изменениям, как упоминалось в других ответах.

Souvik Ray 25.05.2021 11:14

Если это работает, почему существует forwardRef?

Mattia 16.06.2021 14:16

Волшебство! Так же просто, как изменить его с ref на innerRef

David Jones 05.08.2021 09:18
const renderItem = ({ item, index }) => {

        return (
            <>          
            <Item
                key = {item.Id}
                item = {item}
                index = {index}
            />
            </>
        );
    };

Использовать фрагмент для решения React.forwardRef()? предупреждение

Если вы обнаружите, что не можете добавить к компоненту пользовательскую опору ref или forwardRef, у меня есть хитрость, позволяющая получить объект 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.

Одно предложение по объявлению переменной buttonRef может быть более кратким, чтобы использовать необязательную цепочку: const buttonRef = ref.current?.children[0];

huntzinger92 18.01.2022 03:56

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

    const AppTextField =(props) {return(/*your component*/)}

измените следующий код на

const AppTextField = forwardRef((props,ref) {return(/*your component*/)}

В нашем случае мы передавали компонент 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 на это и пуф:

const Header = () => (
  <Link href = {'/'}>
    <div className = {s.headerLogo}>
      <Logo />
    </div>
 </Link>
)

Была аналогичная проблема с созданием пользовательского компонента следующей ссылки, который в основном представляет собой оболочку вокруг стилизованного текстового компонента - решил ее, добавив фрагмент вокруг моего обернутого компонента вместо div.

pr0tipZ 20.11.2021 23:14

Я просто вставляю сюда skychavda решение, так как оно предоставляет ссылку на дочерний элемент: так что вы можете напрямую вызывать дочерний метод или дочернюю ссылку из родителя без каких-либо предупреждений.

источник: https://github.com/reactjs/reactjs.org/issues/2120

/* Child.jsx */
import React from 'react'

class Child extends React.Component {
  componentDidMount() {
    const { childRef } = this.props;
    childRef(this);
  }
  componentWillUnmount() {
   const { childRef } = this.props;
    childRef(undefined);
  }
  alertMessage() {
    window.alert('called from parent component');
  }
  render() {
    return <h1>Hello World!</h1>
  }
}

export default Child;
/* Parent.jsx */
import React from 'react';
import Child from './Child';

class Parent extends React.Component {
  onClick = () => {
    this.child.alertMessage(); // do stuff
  }
  render() {
    return (
      <div>
        <Child childRef = {ref => (this.child = ref)} />
        <button onClick = {this.onClick}>Child.alertMessage()</button>
      </div>
    );
  }
}

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