Next.js: Next 9 - Использование функциональных компонентов как дочерних для<link/> вызывает реф-предупреждения

Созданный на 12 июл. 2019  ·  32Комментарии  ·  Источник: vercel/next.js

Сообщение об ошибке

Опишите ошибку

Использование функционального компонента в качестве дочернего для <Link/> вызывает:

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

Произошло это только после обновления с v8 => v9.

Воспроизводить

Репозиторий воспроизведения: https://github.com/nickluger/nextjs-link-ref-functional-comp-warning

Ожидаемое поведение

<Link/> должен работать с функциональными компонентами / не выводить предупреждения.

Системная информация

  • Версия Next.js: 9.0.1

Самый полезный комментарий

Обернуть все используемые функциональные компоненты в Link вручную ? Разве для этого не должно быть более простого и менее повторяющегося решения? Хоть что-то вроде <Link href="/" forwardRef>...</Link> ?

Все 32 Комментарий

Тоже самое. У меня ошибка, если я использую такой пользовательский компонент:

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

Это происходит только тогда, когда вы используете компонент как дочерний. Например, они не предупреждают:

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

Есть ли способ обойти эту ошибку? мы заблокированы от перехода на 9 для этого, когда некоторые функции, которые мы действительно хотели бы использовать, например, поддержка машинописного текста. Только что заметил, что он поднялся до 9.0.3: /

Вы можете временно отключить звук, например:

// TODO: Muting error, fix as soon as zeit/next.js/issues/7915 resolved
const originalError = console.error;

console.error = (...args) => {
  if (/Warning.*Function components cannot be given refs/.test(args[0])) {
    return;
  }
  originalError.call(console, ...args);
};

У меня такая же проблема.

Если вы используете <Link/> для обертывания пользовательского компонента, вы можете переслать ref следующим образом:

const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
  return (
    <div/>
  );
});
<Link href={"/"}>
  <CustomComponent/>
</Link>

Предупреждение исчезнет.

Я обновился до 9.0.4-canary.2 но все еще получаю предупреждение на консоли. Я что-то упускаю?

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 `Link`.

@ th0th Вы должны обернуть свой компонент в React.forwardRef . Как этот:

import React from 'react'
import Link from 'next/link'

const CustomComponent = React.forwardRef((props, ref) => (
  <a ref={ref} {...props}>
    Click
  </a>
))

export default () => (
  <Link href='/' passHref>
    <CustomComponent/>
  </Link>
)

Обернуть все используемые функциональные компоненты в Link вручную ? Разве для этого не должно быть более простого и менее повторяющегося решения? Хоть что-то вроде <Link href="/" forwardRef>...</Link> ?

Согласитесь с @nickluger, это кажется

Должны ли все другие библиотеки реализовать атрибут forwardRef таким же образом? Или, может быть, создатели отреагировали на мысль, что разработчики будут использовать функцию React.forwardRef вместо реализации атрибута forwardRef ?

Да, согласен с @nickluger , Link .

Следует ли нам снова открыть и переименовать эту проблему (@ijjk) или кто-то уже открыл новую?

Тоже самое. У меня ошибка, если я использую такой пользовательский компонент:

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

Это происходит только тогда, когда вы используете компонент как дочерний. Например, они не предупреждают:

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

Скорее всего, это вызовет ошибку консоли:

Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.

Я столкнулся с этой проблемой при обновлении Next JS. Есть ли исправление в пути?

Я не уверен, что понимаю, как использовать forwardRef и оборачивать свой компонент. Мой файл button.js в настоящее время экспортирует следующее ....

const Button = (props) => {
    return (<stuff />)
}

export default React.memo(Button)

См. Выше, я открыл продолжение здесь: https://github.com/zeit/next.js/issues/8962

Я столкнулся с этой проблемой при обновлении Next JS. Есть ли исправление в пути?

Я не уверен, что понимаю, как использовать forwardRef и оборачивать свой компонент. Мой файл button.js в настоящее время экспортирует следующее ....

const Button = (props) => {
    return (<stuff />)
}

export default React.memo(Button)

В этом случае вы сможете просто сделать

import {forwardRef} from 'react';
const Button = forwardRef(props, ref) => {
    return (<stuff ref={ref} />)
}

для части forwardRef. В документах также упоминается https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-child, хотя я этого не пробовал. Я обнаружил, что делаю это

            <Link
              href={href}
            >
              <a>
                {text}
              </a>
            </Link>

работает (несмотря на то, что выглядит очень странно).

Обнаружение этой проблемы в 9.0.2

Использование <a></a> around может работать, но вызовет другую ошибку, например "must have href" и т. Д. При использовании a11y и подобных.

Изменить: потратил 15 минут, пытаясь понять это, это очень скучно, такая трата времени и, похоже, ведет себя правильно, несмотря на предупреждение.

Лично перейти на https://github.com/zeit/next.js/issues/7915#issuecomment -511792629 намного проще.

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

import React, { Fragment, useRef } from 'react';
import { MyFunctionalComponent } from './my-functional-component';

const App = props => {
  const myRef = useRef();

  return ( 
    <Link href={href}>
      <Fragment>
          <MyFunctionalComponent ref={myRef} />
      </Fragment>
    </Link>
  );
}

Где <MyFunctionalComponent> пересылает ссылку:

import React, { forwardRef } from 'react';

const MyFunctionalComponent = forwardRef(props, ref) => (
  <div ref={ref} />
);

Это не добавляет никакой дополнительной HTML-оболочки в вывод ( <div /> ) и не должно вызывать никаких связанных ошибок.

@ hill84 Интересно, а откуда в вашем примере myRef ?

@Vadorequest Я добавил подробности в свой предыдущий комментарий.

После предложения @ hill84 было хорошее обходное решение:
`` ''
const ButtonLink: FC= ({children, href, ... props}) => (
<

После предложения @ hill84 было хорошее обходное решение:

const ButtonLink: FC<ButtonLinkProps> = ({ children, href, ...props }) => (
  <Link href={href}>
    <><Button link {...props}>{children}</Button></>
  </Link>
);

Я использую <><Component/></> но ссылка не может действовать. Мне нужно использовать <div></div> вместо.

Я предлагаю решение, при котором функция возвращает объект с реквизитом вместо компонента:

const propsUserBtn = user => ({
    className: "h-10 w-10 font-black rounded-full bg-orange-200 text-teal-700",
    title: user.first_name + ' ' + user.last_name,
    children: (user.first_name.charAt(0) + user.last_name.charAt(0)).toUpperCase()
})
<Link href='/profile'>
    <button { ...propsUserBtn(user) } />   
</Link>

Проверил, работает!

Зачем вообще нужен этот реф? Гарантирует ли это правильное размещение href в базовом обернутом компоненте, когда passHref используется в <Link /> ?

Это очень раздражает, поскольку мой пользовательский

Или, по крайней мере, пусть это будет функция выбора, если вам нужно указать размещение href в вашем компоненте. <Link href="/" passHref useRef /> ?

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

Для решения этой проблемы я использую упаковку пользовательского компонента в элемент div как это предлагает @ namlq93, но он также не кажется чистым ...

Тоже самое. У меня ошибка, если я использую такой пользовательский компонент:

        <Link href="/href">
          <Button
            type="custom"
            color="#FCFCFC"
          >
             buttonText
          </Button>
        </Link>

Это происходит только тогда, когда вы используете компонент как дочерний. Например, они не предупреждают:

        <Link href="/href">
          <button
            type="custom"
            color="#FCFCFC"
          >
            buttonText
          </button>
        </Link>

        <Link href="/href">
          <a>
            <Button
              type="custom"
              color="#FCFCFC"
            >
              buttonText
            </Button>
          </a>
        </Link>

Это работает, спасибо, дружище !!

У меня похожая проблема

все еще там

https://nextjs.org/docs/api-reference/next/link#if -the-child-is-a-function-component

Это печально.

На днях я смотрел конференцию NextJS и думал: «Вау, следующее - будущее». Мне очень нравится Next и экосистема Vercel, и я хочу, честно говоря, иметь возможность сказать это и быть сторонником Next. Однако из-за того, что подобные проблемы закрыты и не решены, сделать это сложно. Я встречал этот тип шаблона несколько раз в описанных здесь проблемах, особенно с маршрутизатором.

Со стороны пользователя есть 3 решения этой проблемы, и ни одно из них не является отличным DX.

  1. Рекомендуемый способ React.forwardRef. оберните компонент в React.forwardRef . Это может быть очень повторяющимся
  2. Оберните функциональный компонент в такой тег, как div , span , a и т. Д.
  3. Вместо Link подключите useRouter и используйте router.push

Независимо от того, какое решение вы используете, они все странные и требуют комментариев, связанных с этой проблемой, или документов, чтобы объяснить коллегам / участникам, почему это необходимо для предотвращения случайного удаления / очистки.

Думаю, этот вопрос следует снова открыть для обсуждения.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги