Next.js: التالي 9 - استخدام المكونات الوظيفية كعنصر تابع لـ<link/> يسبب تحذيرات المرجع

تم إنشاؤها على ١٢ يوليو ٢٠١٩  ·  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
bug

التعليق الأكثر فائدة

التفاف جميع المكونات الوظيفية المستخدمة داخل 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} />)
}

للجزء الأمامي تذكر المستندات أيضًا 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> حوله ، ولكنه سيؤدي إلى حدوث خطأ آخر مثل "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 لقد أضفت المزيد من التفاصيل إلى تعليقي السابق.

كان اتباع اقتراح
""
زر const ButtonLink: FC= ({children، href، ... props}) => (
<

كان اتباع اقتراح

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 في ذلك اليوم وأنا أفكر في "Wow Next هو المستقبل". تعجبني حقًا Next ونظام Vercel البيئي وأريد أن أكون قادرًا بصدق على قول ذلك وأن أكون من المدافعين عن Next. ومع ذلك ، فإن إغلاق مثل هذه القضايا وعدم معالجتها يجعل من الصعب القيام بذلك. لقد رأيت هذا النوع من الأنماط عدة مرات خلال المشكلات هنا ، خاصةً مع جهاز التوجيه.

هناك 3 حلول لهذه المشكلة من جانب المستخدم ولا يوجد أي منها حل DX رائع.

  1. الطريقة الموصى بها React.forwardRef. التفاف المكون في React.forwardRef . يمكن أن يكون هذا متكررًا جدًا
  2. لف المكون الوظيفي في علامة مثل div ، span ، a ، إلخ.
  3. بدلاً من Link ، اسحب useRouter واستخدم router.push

بغض النظر عن الحل الذي تستخدمه ، فهي كلها غريبة وتتطلب تعليقات مرتبطة بهذه المشكلة أو المستندات لشرح لزملاء العمل / المساهمين سبب حاجتها لمنع الإزالة / التنظيف العرضي.

أعتقد أنه يجب إعادة فتح هذه القضية للمناقشة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات