Die Verwendung einer Funktionskomponente als untergeordnetes Element von <Link/>
verursacht:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Dies geschah erst nach einem Upgrade von v8 => v9.
Reproduktions-Repo: https://github.com/nickluger/nextjs-link-ref-functional-comp-warning
<Link/>
sollte auch mit Funktionskomponenten funktionieren / keine Warnung anzeigen.
Hier gilt das gleiche. Ich habe einen Fehler Wenn ich eine benutzerdefinierte Komponente wie diese verwende:
<Link href="/href">
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</Link>
Dies geschieht nur, wenn Sie eine Komponente als untergeordnetes Element verwenden. Diese geben zum Beispiel keine Warnung:
<Link href="/href">
<button
type="custom"
color="#FCFCFC"
>
buttonText
</button>
</Link>
<Link href="/href">
<a>
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</a>
</Link>
Gibt es einen Weg, um diesen Fehler zu umgehen? Wir sind für diesen Fall daran gehindert, auf 9 zu wechseln, wenn einige Funktionen, die wir wirklich nutzen möchten, wie die Typoskript-Unterstützung. Ich habe gerade bemerkt, dass es auf 9.0.3 gestoßen ist: /
Sie können versuchen, es vorübergehend stummzuschalten, z.
// 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);
};
Ich habe hier das gleiche Problem.
Wenn Sie <Link/>
, um Ihre benutzerdefinierte Komponente zu verpacken, können Sie ref
wie folgt weiterleiten:
const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
return (
<div/>
);
});
<Link href={"/"}>
<CustomComponent/>
</Link>
Die Warnung verschwindet.
Ich habe auf 9.0.4-canary.2
aktualisiert, erhalte aber immer noch die Warnung auf der Konsole. Vermisse ich etwas
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 Du solltest deine Komponente in React.forwardRef
einschließen . Wie dieser:
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>
)
Alle in einem Link
manuell verpacken ? Sollte es dafür keine einfachere, weniger sich wiederholende Lösung geben? Zumindest so etwas wie <Link href="/" forwardRef>...</Link>
?
Stimmen Sie mit
Sollten alle anderen Bibliotheken das Attribut forwardRef
auf dieselbe Weise implementieren? Oder vielleicht reagieren die Entwickler, dass Entwickler die Funktion React.forwardRef
verwenden, anstatt das Attribut forwardRef
implementieren?
Ja, stimme @nickluger zu , es ist Link
zu tun.
Sollten wir dieses Problem erneut öffnen und umbenennen (@ijjk) oder hat jemand bereits ein neues geöffnet?
Hier gilt das gleiche. Ich habe einen Fehler Wenn ich eine benutzerdefinierte Komponente wie diese verwende:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Dies geschieht nur, wenn Sie eine Komponente als untergeordnetes Element verwenden. Diese geben zum Beispiel keine Warnung:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Dies wird höchstwahrscheinlich einen Konsolenfehler auslösen:
Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
Ich habe dieses Problem gerade beim Upgrade von Next JS festgestellt. Gibt es eine Lösung auf dem Weg?
Ich bin nicht sicher, ob ich verstehe, wie man forwardRef verwendet und meine Komponente umschließt. Meine button.js-Datei exportiert derzeit Folgendes ....
const Button = (props) => {
return (<stuff />)
}
export default React.memo(Button)
Siehe oben, ich habe hier ein Follow-up eröffnet: https://github.com/zeit/next.js/issues/8962
Ich habe dieses Problem gerade beim Upgrade von Next JS festgestellt. Gibt es eine Lösung auf dem Weg?
Ich bin nicht sicher, ob ich verstehe, wie man forwardRef verwendet und meine Komponente umschließt. Meine button.js-Datei exportiert derzeit Folgendes ....
const Button = (props) => { return (<stuff />) } export default React.memo(Button)
In diesem Fall sollten Sie in der Lage sein, dies einfach zu tun
import {forwardRef} from 'react';
const Button = forwardRef(props, ref) => {
return (<stuff ref={ref} />)
}
für den forwardRef-Teil. In den Dokumenten wird auch https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-child erwähnt, obwohl ich das nicht ausprobiert habe. Ich habe das dabei gefunden
<Link
href={href}
>
<a>
{text}
</a>
</Link>
funktioniert (obwohl es sehr seltsam aussieht.)
Auf dieses Problem in 9.0.2 stoßen
Die Verwendung von <a></a>
around funktioniert möglicherweise, löst jedoch andere Fehler aus, z. B. "muss href haben" usw., wenn a11y und ähnliches verwendet wird.
Bearbeiten: Ich habe 15 Minuten damit verbracht, dies herauszufinden. Es ist sehr langweilig, eine solche Zeitverschwendung und scheint sich trotz der Warnung richtig zu verhalten.
Persönlich ist es viel einfacher, https://github.com/zeit/next.js/issues/7915#issuecomment -511792629 zu wählen.
Was ist mit dieser Lösung ein Fragment reagieren als Lager Wrapper?
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>
);
}
Wobei <MyFunctionalComponent>
den Schiedsrichter weiterleitet:
import React, { forwardRef } from 'react';
const MyFunctionalComponent = forwardRef(props, ref) => (
<div ref={ref} />
);
Dies fügt der Ausgabe keinen zusätzlichen HTML-Wrapper hinzu ( <div />
) und sollte keinen verwandten Fehler auslösen.
@ hill84 Interessant, aber woher kommt myRef
in Ihrem Beispiel?
@Vadorequest Ich habe meinem vorherigen Kommentar weitere Details hinzugefügt.
Dem Vorschlag von gute Lösung :
`` `
const ButtonLink: FC
<
Dem Vorschlag von gute Lösung :
const ButtonLink: FC<ButtonLinkProps> = ({ children, href, ...props }) => ( <Link href={href}> <><Button link {...props}>{children}</Button></> </Link> );
Ich benutze <><Component/></>
aber Link kann nicht handeln. Ich muss stattdessen <div></div>
verwenden.
Ich schlage eine Lösung vor, bei der eine Funktion ein Objekt mit Requisiten anstelle einer Komponente zurückgibt:
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>
Überprüft, es funktioniert!
Warum wird dieser Schiedsrichter überhaupt benötigt? Soll die korrekte Platzierung von href
in der zugrunde liegenden verpackten Komponente gewährleistet werden, wenn passHref
in <Link />
?
Dies ist sehr ärgerlich, da meine benutzerdefinierte Komponente die <a>
im Stammverzeichnis hat und ich sehe, dass sie ohnehin korrekt darauf angewendet wird ... Ich würde es viel lieber erzwingen lassen, dass Sie Ihre zugrunde liegende benutzerdefinierte Komponente benötigen Habe den Anker an der Wurzel und vermeide diese ganze ref
Design-Entscheidung.
React.forwardRef
ist eine schrecklich umständliche Sache, um die Leute zur Implementierung zu zwingen, und spielt die Hölle mit meinen Lintern 😞
Oder zumindest eine Opt-In-Funktion, wenn Sie die Platzierung von href
in Ihrer Komponente angeben müssen. <Link href="/" passHref useRef />
?
Ich denke nicht, dass es eine gute Lösung ist, ein anderes Modul erstellen zu müssen, um den Ref an eine benutzerdefinierte Komponente weiterzuleiten, und es ist auch zu repetitiv.
Die Art und Weise, wie ich dieses Problem behandle , besteht darin, die benutzerdefinierte Komponente mit einem div
-Element zu versehen, wie von @ namlq93 vorgeschlagen, aber es scheint auch nicht sauber zu sein ...
Hier gilt das gleiche. Ich habe einen Fehler Wenn ich eine benutzerdefinierte Komponente wie diese verwende:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Dies geschieht nur, wenn Sie eine Komponente als untergeordnetes Element verwenden. Diese geben zum Beispiel keine Warnung:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Es funktioniert, danke Kumpel !!
Habe ein ähnliches Problem
noch da
https://nextjs.org/docs/api-reference/next/link#if -the-child-is-a-function-component
Das ist traurig.
Ich habe neulich die NextJS-Konferenz gesehen und gedacht "Wow Next ist die Zukunft". Ich mag Next und das Vercel-Ökosystem sehr und ich möchte das ehrlich sagen und ein Anwalt für Next sein können. Probleme wie diese, die geschlossen und nicht angesprochen werden, machen es jedoch schwierig, dies zu tun. Ich habe diese Art von Muster in den hier aufgeführten Problemen mehrmals gesehen, insbesondere beim Router.
Es gibt 3 Lösungen für dieses Problem von der Benutzerseite und keine von ihnen ist großartig DX.
React.forwardRef
. Dies kann sich sehr wiederholendiv
, span
, a
usw. ein.router.push
Unabhängig davon, welche Lösung Sie verwenden, sind sie alle seltsam und erfordern Kommentare, die auf dieses Problem oder die Dokumente verweisen , um Mitarbeitern / Mitwirkenden zu erklären, warum dies erforderlich ist, um ein versehentliches Entfernen / Bereinigen zu verhindern.
Ich denke, dieses Thema sollte wieder zur Diskussion gestellt werden.
Hilfreichster Kommentar
Alle in einem
Link
manuell verpacken ? Sollte es dafür keine einfachere, weniger sich wiederholende Lösung geben? Zumindest so etwas wie<Link href="/" forwardRef>...</Link>
?