Next.js: Berikutnya 9 - Menggunakan komponen fungsional sebagai anak<link/> menyebabkan peringatan ref

Dibuat pada 12 Jul 2019  ·  32Komentar  ·  Sumber: vercel/next.js

Laporan bug

Jelaskan bugnya

Menggunakan komponen fungsional sebagai anak dari <Link/> menyebabkan:

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

Ini terjadi hanya setelah memutakhirkan dari v8 => v9.

Untuk Mereproduksi

Reproduksi repo: https://github.com/nickluger/nextjs-link-ref-functional-comp-warning

Perilaku yang diharapkan

<Link/> harus bekerja dengan komponen fungsional, juga / tidak menampilkan peringatan.

Sistem Informasi

  • Versi Next.js: 9.0.1
bug

Komentar yang paling membantu

Bungkus semua komponen fungsional yang digunakan dalam Link secara manual ? Tidakkah seharusnya ada solusi yang lebih mudah dan tidak berulang untuk ini? Setidaknya sesuatu seperti <Link href="/" forwardRef>...</Link> ?

Semua 32 komentar

Sama disini. Saya mengalami kesalahan jika saya menggunakan komponen khusus seperti ini:

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

Ini hanya terjadi saat Anda menggunakan komponen sebagai anak. Ini tidak memberi peringatan misalnya:

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

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

Apakah ada cara untuk mengatasi bug ini? kami diblokir dari pergi ke 9 untuk yang satu ini ketika beberapa fitur kami benar-benar ingin memanfaatkan seperti dukungan naskah. Baru saja menyadarinya naik ke 9.0.3: /

Anda dapat mencoba menonaktifkannya untuk sementara, seperti:

// 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);
};

Saya mengalami masalah yang sama di sini.

Jika Anda menggunakan <Link/> untuk membungkus komponen kustom Anda, Anda dapat meneruskan ref seperti ini:

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

Peringatan itu hilang.

Saya telah memperbarui ke 9.0.4-canary.2 tetapi saya masih mendapatkan peringatan di konsol. Apakah saya melewatkan sesuatu?

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 Anda harus membungkus komponen Anda dengan React.forwardRef . Seperti yang ini:

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>
)

Bungkus semua komponen fungsional yang digunakan dalam Link secara manual ? Tidakkah seharusnya ada solusi yang lebih mudah dan tidak berulang untuk ini? Setidaknya sesuatu seperti <Link href="/" forwardRef>...</Link> ?

Setuju dengan @nickluger, ini tampaknya kontra-intuitif.

Haruskah semua perpustakaan lain menerapkan atribut forwardRef dengan cara yang sama? Atau mungkin pembuat reaksinya mengira bahwa pengembang akan menggunakan fungsi React.forwardRef daripada menerapkan atribut forwardRef ?

Ya setuju dengan @nickluger , itu menyakitkan untuk melakukan ini secara manual untuk semua komponen di dalam Link .

Haruskah kami membuka kembali dan mengganti nama masalah ini (@ijjk) atau apakah seseorang sudah membuka yang baru?

Sama disini. Saya mengalami kesalahan jika saya menggunakan komponen khusus seperti ini:

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

Ini hanya terjadi saat Anda menggunakan komponen sebagai anak. Ini tidak memberi peringatan misalnya:

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

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

Ini kemungkinan besar akan memunculkan kesalahan konsol:

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

Saya baru saja mengalami masalah ini saat memutakhirkan JS Berikutnya. Apakah ada perbaikan di jalan?

Saya tidak yakin saya mengerti bagaimana menggunakan forwardRef dan membungkus komponen saya. File button.js saya saat ini mengekspor berikut ....

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

export default React.memo(Button)

Lihat di atas, saya membuka tindak lanjut di sini: https://github.com/zeit/next.js/issues/8962

Saya baru saja mengalami masalah ini saat memutakhirkan JS Berikutnya. Apakah ada perbaikan di jalan?

Saya tidak yakin saya mengerti bagaimana menggunakan forwardRef dan membungkus komponen saya. File button.js saya saat ini mengekspor berikut ....

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

export default React.memo(Button)

Dalam hal ini, Anda seharusnya bisa melakukannya

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

untuk bagian forwardRef. Dokumen tersebut juga menyebutkan https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-child, meskipun saya belum mencobanya. Saya telah menemukan bahwa melakukan ini

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

berhasil (meski terlihat sangat aneh.)

Mengalami masalah ini di 9.0.2

Menggunakan <a></a> sekitar mungkin berhasil, tetapi akan memicu kesalahan lain seperti "harus memiliki href", dll. Saat menggunakan a11y dan serupa.

Sunting: Menghabiskan 15 juta untuk mencoba mencari tahu ini, itu sangat membosankan, membuang-buang waktu, dan tampaknya berperilaku baik meskipun ada peringatan.

Secara pribadi, membuka https://github.com/zeit/next.js/issues/7915#issuecomment -511792629 jauh lebih mudah.

Bagaimana dengan solusi ini dengan menggunakan fragmen reaksi sebagai pembungkus bantalan?

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>
  );
}

Dimana <MyFunctionalComponent> meneruskan ref:

import React, { forwardRef } from 'react';

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

Ini tidak menambahkan pembungkus HTML tambahan dalam keluaran ( <div /> ) dan seharusnya tidak memicu kesalahan terkait.

@ hill84 Menarik, tetapi dari mana myRef berasal dalam contoh Anda?

@Vadorequest Saya telah menambahkan lebih banyak detail ke komentar saya sebelumnya.

Mengikuti saran @ hill84 adalah solusi yang bagus:
``
const ButtonLink: FC= ({anak-anak, href, ... props}) => (
<

Mengikuti saran @ hill84 adalah solusi yang bagus:

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

Saya menggunakan <><Component/></> tetapi Link tidak dapat bertindak. Saya harus menggunakan <div></div> sebagai ganti.

Saya menyarankan solusi di mana suatu fungsi mengembalikan objek dengan props alih-alih komponen:

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>

Sudah diperiksa, berhasil!

Mengapa ref ini bahkan dibutuhkan? Apakah itu untuk menjamin penempatan yang benar dari href dalam komponen terbungkus dasar ketika passHref digunakan dalam <Link /> ?

Ini sangat menjengkelkan karena

Atau setidaknya jadikan itu fitur keikutsertaan jika Anda perlu menentukan penempatan href di komponen Anda. <Link href="/" passHref useRef /> ?

Saya tidak berpikir bahwa harus membuat modul lain untuk meneruskan referensi ke komponen khusus adalah solusi yang baik dan juga terlalu berulang.

Cara yang saya gunakan untuk menangani masalah ini adalah dengan membungkus komponen khusus dengan elemen div seperti yang disarankan oleh @ namlq93 tetapi tampaknya juga tidak bersih ...

Sama disini. Saya mengalami kesalahan jika saya menggunakan komponen khusus seperti ini:

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

Ini hanya terjadi saat Anda menggunakan komponen sebagai anak. Ini tidak memberi peringatan misalnya:

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

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

Berhasil, terima kasih sobat !!

Saya mengalami masalah serupa

masih di sana

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

Ini menyedihkan.

Saya menonton konferensi NextJS tempo hari sambil berpikir "Wow Berikutnya adalah masa depan". Saya sangat menyukai ekosistem Next dan Vercel dan saya ingin secara jujur ​​mengatakan itu dan menjadi pendukung Next. Namun, masalah seperti ini ditutup dan tidak ditangani membuat sulit untuk melakukannya. Saya telah melihat jenis pola ini beberapa kali sepanjang masalah di sini, khususnya dengan Router.

Ada 3 solusi untuk masalah ini dari sisi pengguna dan tidak satupun dari mereka adalah DX yang hebat.

  1. Cara yang direkomendasikan React.forwardRef. bungkus komponen dalam React.forwardRef . Ini bisa sangat berulang
  2. Bungkus komponen fungsional dalam tag seperti div , span , a , dll.
  3. Alih-alih Link, tarik useRouter dan gunakan router.push

Apa pun solusi yang Anda gunakan, semuanya aneh dan memerlukan komentar yang ditautkan ke masalah ini atau dokumen untuk menjelaskan kepada rekan kerja / kontributor mengapa ini diperlukan untuk mencegah penghapusan / pembersihan tidak disengaja.

Saya pikir masalah ini harus dibuka kembali untuk diskusi.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat