L'utilisation d'un composant fonctionnel comme enfant de <Link/>
provoque:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Cela ne s'est produit qu'après la mise à niveau de v8 => v9.
Repo de reproduction: https://github.com/nickluger/nextjs-link-ref-functional-comp-warning
<Link/>
devrait également fonctionner avec les composants fonctionnels / ne pas afficher d'avertissement.
Pareil ici. J'ai une erreur si j'utilise un composant personnalisé comme celui-ci:
<Link href="/href">
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</Link>
Cela ne se produit que lorsque vous utilisez un composant en tant qu'enfant. Ceux-ci ne donnent pas d'avertissement par exemple:
<Link href="/href">
<button
type="custom"
color="#FCFCFC"
>
buttonText
</button>
</Link>
<Link href="/href">
<a>
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</a>
</Link>
Y a-t-il un moyen de contourner ce bug? nous ne pouvons pas passer à 9 pour celui-ci lorsque certaines fonctionnalités que nous aimerions vraiment exploiter comme le support dactylographié. Je viens de remarquer qu'il est passé à 9.0.3: /
Vous pouvez essayer de le désactiver temporairement, comme:
// 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);
};
J'ai le même problème ici.
Si vous utilisez <Link/>
pour envelopper votre composant personnalisé, vous pouvez transférer ref
comme ceci:
const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
return (
<div/>
);
});
<Link href={"/"}>
<CustomComponent/>
</Link>
L'avertissement disparaît.
J'ai mis à jour vers 9.0.4-canary.2
mais je reçois toujours l'avertissement sur la console. Est-ce que je manque quelque chose?
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 Vous devez envelopper votre composant dans React.forwardRef
. Comme celui-ci:
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>
)
Enveloppez manuellement tous les composants fonctionnels utilisés dans un Link
? Ne devrait-il pas y avoir une solution plus simple et moins répétitive pour cela? Au moins quelque chose comme <Link href="/" forwardRef>...</Link>
?
D'accord avec @nickluger, cela semble contre-intuitif.
Toutes les autres bibliothèques devraient-elles implémenter l'attribut forwardRef
de la même manière? Ou peut-être que les créateurs de React ont pensé que les développeurs utiliseraient la fonction React.forwardRef
au lieu d'implémenter l'attribut forwardRef
?
Oui d'accord avec @nickluger , c'est Link
.
Devrions-nous rouvrir et renommer ce numéro (@ijjk) ou est-ce que quelqu'un en a déjà ouvert un nouveau?
Pareil ici. J'ai une erreur si j'utilise un composant personnalisé comme celui-ci:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Cela ne se produit que lorsque vous utilisez un composant en tant qu'enfant. Ceux-ci ne donnent pas d'avertissement par exemple:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Cela générera très probablement une erreur de console:
Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
Je viens de rencontrer ce problème lors de la mise à niveau de Next JS. Y a-t-il une solution en cours?
Je ne suis pas sûr de comprendre comment utiliser forwardRef et encapsuler mon composant. Mon fichier button.js exporte actuellement les éléments suivants ...
const Button = (props) => {
return (<stuff />)
}
export default React.memo(Button)
Voir ci-dessus, j'ai ouvert un suivi ici: https://github.com/zeit/next.js/issues/8962
Je viens de rencontrer ce problème lors de la mise à niveau de Next JS. Y a-t-il une solution en cours?
Je ne suis pas sûr de comprendre comment utiliser forwardRef et encapsuler mon composant. Mon fichier button.js exporte actuellement les éléments suivants ...
const Button = (props) => { return (<stuff />) } export default React.memo(Button)
Dans ce cas, vous devriez pouvoir simplement faire
import {forwardRef} from 'react';
const Button = forwardRef(props, ref) => {
return (<stuff ref={ref} />)
}
pour la partie forwardRef. La documentation mentionne également https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-child, bien que je n'ai pas essayé cela. J'ai trouvé ça en faisant ça
<Link
href={href}
>
<a>
{text}
</a>
</Link>
fonctionne (bien que cela semble très étrange.)
Rencontrer ce problème dans la version 9.0.2
L'utilisation de <a></a>
around peut fonctionner, mais déclenchera d'autres erreurs comme "must have href", etc. lors de l'utilisation de a11y et similaire.
Edit: J'ai passé 15 minutes à essayer de comprendre cela, c'est très ennuyeux, une telle perte de temps, et semble se comporter correctement malgré l'avertissement.
Personnellement, aller pour https://github.com/zeit/next.js/issues/7915#issuecomment -511792629 beaucoup plus facile.
Qu'en est-il de cette solution utilisant un fragment de réaction comme enveloppe de roulement?
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>
);
}
Où <MyFunctionalComponent>
transfère la référence:
import React, { forwardRef } from 'react';
const MyFunctionalComponent = forwardRef(props, ref) => (
<div ref={ref} />
);
Cela n'ajoute aucun wrapper HTML supplémentaire dans la sortie ( <div />
) et ne devrait pas déclencher d'erreur connexe.
@ hill84 Intéressant, mais d'où vient myRef
dans votre exemple?
@Vadorequest J'ai ajouté plus de détails à mon commentaire précédent.
Suivre la suggestion de @ hill84 était une bonne solution:
''
Const ButtonLink: FC
<
Suivre la suggestion de @ hill84 était une bonne solution:
const ButtonLink: FC<ButtonLinkProps> = ({ children, href, ...props }) => ( <Link href={href}> <><Button link {...props}>{children}</Button></> </Link> );
J'utilise <><Component/></>
mais Link ne peut pas agir. Je dois utiliser <div></div>
au lieu de.
Je suggère une solution où une fonction renvoie un objet avec des accessoires au lieu d'un composant:
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>
Vérifié, ça marche!
Pourquoi cette référence est-elle même nécessaire? Est-ce pour garantir le placement correct du href
dans le composant encapsulé sous-jacent lorsque passHref
est utilisé dans le <Link />
?
C'est super ennuyeux car mon composant personnalisé <a>
à la racine et je peux voir qu'il est appliqué correctement de toute façon href ... Je préfère de loin qu'il soit imposé que vous ayez besoin de votre composant personnalisé sous-jacent pour ont l'ancre à la racine et d' éviter tout ce ref
desicion design.
React.forwardRef
est une chose horriblement encombrante à forcer les gens à mettre en œuvre et joue l'enfer avec mes linters 😞
Ou au moins, faites-en une fonctionnalité optionnelle si vous devez spécifier l'emplacement du href
dans votre composant. <Link href="/" passHref useRef />
?
Je ne pense pas que devoir créer un autre module pour transmettre la référence à un composant personnalisé soit une bonne solution et aussi trop répétitif.
La façon dont j'utilise pour gérer ce problème consiste à envelopper le composant personnalisé avec un élément div
comme suggéré par @ namlq93, mais il ne semble pas non plus propre ...
Pareil ici. J'ai une erreur si j'utilise un composant personnalisé comme celui-ci:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Cela ne se produit que lorsque vous utilisez un composant en tant qu'enfant. Ceux-ci ne donnent pas d'avertissement par exemple:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Cela fonctionne, merci mon pote !!
J'ai un problème similaire
toujours là
https://nextjs.org/docs/api-reference/next/link#if -the-child-is-a-function-component
C'est triste.
Je regardais la conférence NextJS l'autre jour en pensant "Wow Next is the future". J'aime beaucoup Next et l'écosystème Vercel et je veux honnêtement pouvoir le dire et être un défenseur de Next. Cependant, des problèmes comme ceux-ci étant clos et non résolus, il est difficile de le faire. J'ai vu ce type de modèle plusieurs fois tout au long des problèmes ici, en particulier avec le routeur.
Il existe 3 solutions à ce problème du côté utilisateur et aucune d'entre elles n'est excellente DX.
React.forwardRef
. Cela peut être très répétitifdiv
, span
, a
, etc.router.push
Quelle que soit la solution que vous utilisez, elles sont toutes étranges et nécessitent des commentaires liés à ce problème ou à la documentation pour expliquer aux collègues / contributeurs pourquoi cela est nécessaire pour éviter toute suppression / nettoyage accidentel.
Je pense que cette question devrait être rouverte pour discussion.
Commentaire le plus utile
Enveloppez manuellement tous les composants fonctionnels utilisés dans un
Link
? Ne devrait-il pas y avoir une solution plus simple et moins répétitive pour cela? Au moins quelque chose comme<Link href="/" forwardRef>...</Link>
?