Next.js: 次へ9-機能コンポーネントをの子として使用する<link/> ref-warningsを引き起こします

作成日 2019年07月12日  ·  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

予想される行動

<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属性を実装する必要がありますか? あるいは、開発者がforwardRef属性を実装する代わりにReact.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

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>を使用すると機能する場合がありますが、a11yなどを使用すると、「musthavehref」などの他のエラーがトリガーされます。

編集:これを理解するために15分を費やしました、それは非常に退屈で、そのような時間の無駄であり、警告にもかかわらず適切に動作するようです。

個人的には、 https: //github.com/zeit/next.js/issues/7915#issuecomment-511792629に行く方がはるかに簡単です。

ベアリングラッパーとしてreactフラグメントを使用するこのソリューションはどうですか?

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

これにより、出力( <div /> )にHTMLラッパーが追加されることはなく、関連するエラーが発生することもありません。

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

チェックして、動作します!

なぜこの参照が必要なのですか? passHref<Link />使用されている場合、基になるラップされたコンポーネントでのhrefの正しい配置を保証するためですか?

私のカスタム

または、コンポーネント内のhrefの配置を指定する必要がある場合は、少なくともオプトイン機能にする必要があります。 <Link href="/" passHref useRef />

参照をカスタムコンポーネントに転送するために別のモジュールを作成する必要があることは良い解決策ではなく、繰り返しが多すぎると思います。

私がこの問題を処理するために使用している方法は、 @ namlq93によって提案されているようにカスタムコンポーネントをdiv要素でラップすること

こっちも一緒。 次のようなカスタムコンポーネントを使用すると、エラーが発生します。

        <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

これは悲しいです。

先日、「Wow Next isthefuture」と思ってNextJSカンファレンスを見ていました。 私はNextとVercelエコシステムが本当に好きで、正直に言ってNextの支持者になりたいと思っています。 ただし、このような問題は解決されておらず、対処されていないため、そうすることは困難です。 私はここでの問題を通して、特にルーターで、このタイプのパターンを何度も見ました。

この問題にはユーザー側から3つの解決策があり、どれも優れたDXではありません。

  1. 推奨される方法React.forwardRef。 コンポーネントをReact.forwardRefでラップします。 これは非常に繰り返しになる可能性があります
  2. 機能コンポーネントをdivspanaなどのタグでラップします。
  3. リンクの代わりに、useRouterをプルして、 router.pushを使用します

どのソリューションを使用しても、それらはすべて奇妙であり、偶発的な削除/クリーンアップを防ぐ必要がある理由を同僚/寄稿者に説明するために、この問題またはドキュメントにリンクするコメントが必要です。

この問題は議論のために再開されるべきだと思います。

このページは役に立ちましたか?
0 / 5 - 0 評価