El uso de un componente funcional como hijo de <Link/>
provoca:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Esto sucedió solo después de actualizar desde v8 => v9.
Repo de reproducción: https://github.com/nickluger/nextjs-link-ref-functional-comp-warning
<Link/>
debería funcionar con componentes funcionales / no mostrar una advertencia.
Igual que aquí. Tengo un error si uso un componente personalizado como este:
<Link href="/href">
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</Link>
Esto solo sucede cuando usa un componente cuando era niño. Estos no dan una advertencia, por ejemplo:
<Link href="/href">
<button
type="custom"
color="#FCFCFC"
>
buttonText
</button>
</Link>
<Link href="/href">
<a>
<Button
type="custom"
color="#FCFCFC"
>
buttonText
</Button>
</a>
</Link>
¿Hay alguna forma de evitar este error? estamos bloqueados para pasar al 9 para este cuando algunas características que realmente nos gustaría aprovechar como el soporte de mecanografiado. Acabo de notar que saltó a 9.0.3: /
Podría intentar silenciarlo temporalmente, como:
// 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);
};
Tengo el mismo problema aquí.
Si usa <Link/>
para envolver su componente personalizado, podría reenviar ref
así:
const CustomComponent = React.forwardRef(function CustomComponent(props, ref) {
return (
<div/>
);
});
<Link href={"/"}>
<CustomComponent/>
</Link>
La advertencia desaparece.
He actualizado a 9.0.4-canary.2
pero todavía recibo la advertencia en la consola. ¿Me estoy perdiendo de algo?
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 Debes envolver tu componente en React.forwardRef
. Como éste:
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>
)
Envuelva todos los componentes funcionales utilizados dentro de un Link
manualmente ? ¿No debería haber una solución más fácil y menos repetitiva para esto? ¿Al menos algo como <Link href="/" forwardRef>...</Link>
?
De acuerdo con @nickluger, esto parece contrario a la intuición.
¿Todas las demás bibliotecas deberían implementar el atributo forwardRef
de la misma manera? ¿O tal vez los creadores de Reacción pensaron que los desarrolladores usarían la función React.forwardRef
lugar de implementar el atributo forwardRef
?
Sí, de acuerdo con @nickluger , es una molestia hacer esto manualmente para todos los componentes dentro de un Link
.
¿Deberíamos reabrir y cambiar el nombre de este problema (@ijjk) o alguien ya abrió uno nuevo?
Igual que aquí. Tengo un error si uso un componente personalizado como este:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Esto solo sucede cuando usa un componente cuando era niño. Estos no dan una advertencia, por ejemplo:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Lo más probable es que esto arroje un error de consola:
Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
Acabo de encontrar este problema al actualizar Next JS. ¿Hay alguna solución en el camino?
No estoy seguro de entender cómo usar forwardRef y envolver mi componente. Mi archivo button.js actualmente exporta lo siguiente ...
const Button = (props) => {
return (<stuff />)
}
export default React.memo(Button)
Ver arriba, abrí un seguimiento aquí: https://github.com/zeit/next.js/issues/8962
Acabo de encontrar este problema al actualizar Next JS. ¿Hay alguna solución en el camino?
No estoy seguro de entender cómo usar forwardRef y envolver mi componente. Mi archivo button.js actualmente exporta lo siguiente ...
const Button = (props) => { return (<stuff />) } export default React.memo(Button)
En este caso, debería poder hacer
import {forwardRef} from 'react';
const Button = forwardRef(props, ref) => {
return (<stuff ref={ref} />)
}
para la parte forwardRef. Los documentos también mencionan https://nextjs.org/docs#forcing -the-link-to-expose-href-to-its-child, aunque no lo he probado. He descubierto que haciendo esto
<Link
href={href}
>
<a>
{text}
</a>
</Link>
funciona (a pesar de parecer muy extraño).
Encontrando este problema en 9.0.2
Usar <a></a>
alrededor puede funcionar, pero desencadenará otro error como "debe tener href", etc. al usar a11y y similares.
Editar: Pasé 15 minutos tratando de resolver esto, es muy aburrido, una pérdida de tiempo y parece comportarse correctamente a pesar de la advertencia.
Personalmente, ir a https://github.com/zeit/next.js/issues/7915#issuecomment -511792629 es mucho más fácil.
¿Qué pasa con esta solución que usa un fragmento de reacción como envoltorio de cojinete?
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>
);
}
Donde <MyFunctionalComponent>
reenvía la referencia:
import React, { forwardRef } from 'react';
const MyFunctionalComponent = forwardRef(props, ref) => (
<div ref={ref} />
);
Esto no agrega ningún contenedor HTML adicional en la salida ( <div />
) y no debería desencadenar ningún error relacionado.
@ hill84 Interesante, pero ¿de dónde viene myRef
en su ejemplo?
@Vadorequest He agregado más detalles a mi comentario anterior.
Seguir la sugerencia de @ hill84 fue una buena solución:
''
const ButtonLink: FC
<
Seguir la sugerencia de @ hill84 fue una buena solución:
const ButtonLink: FC<ButtonLinkProps> = ({ children, href, ...props }) => ( <Link href={href}> <><Button link {...props}>{children}</Button></> </Link> );
Utilizo <><Component/></>
pero Link no puede actuar. Tengo que usar <div></div>
lugar de.
Sugiero una solución donde una función devuelve un objeto con accesorios en lugar de un componente:
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>
Comprobado, funciona!
¿Por qué se necesita esta referencia? ¿Es para garantizar la ubicación correcta de href
en el componente envuelto subyacente cuando se usa passHref
en <Link />
?
Esto es muy molesto ya que mi componente personalizado <a>
en la raíz y puedo ver que se está aplicando href correctamente de todos modos ... Preferiría que se hiciera cumplir que necesita su componente personalizado subyacente para tenga el ancla en la raíz y evite toda esta ref
decisión de diseño.
React.forwardRef
es una cosa horriblemente engorrosa para obligar a la gente a implementar y está jugando al infierno con mis linters 😞
O al menos que sea una función opcional si necesita especificar la ubicación de href
en su componente. <Link href="/" passHref useRef />
?
No creo que tener que crear otro módulo para reenviar la referencia a un componente personalizado sea una buena solución y también es demasiado repetitivo.
La forma en que estoy usando para manejar este problema es envolviendo el componente personalizado con un elemento div
como lo sugiere @ namlq93, pero tampoco parece estar limpio ...
Igual que aquí. Tengo un error si uso un componente personalizado como este:
<Link href="/href"> <Button type="custom" color="#FCFCFC" > buttonText </Button> </Link>
Esto solo sucede cuando usa un componente cuando era niño. Estos no dan una advertencia, por ejemplo:
<Link href="/href"> <button type="custom" color="#FCFCFC" > buttonText </button> </Link> <Link href="/href"> <a> <Button type="custom" color="#FCFCFC" > buttonText </Button> </a> </Link>
Funciona, gracias amigo !!
Estoy teniendo un problema similar
aún allí
https://nextjs.org/docs/api-reference/next/link#if -the-child-is-a-function-component
Esto es triste.
Estaba viendo la conferencia de NextJS el otro día pensando "Wow Next es el futuro". Me gusta mucho Next y el ecosistema de Vercel y, honestamente, quiero poder decir eso y ser un defensor de Next. Sin embargo, problemas como estos que se cierran y no se abordan dificultan hacerlo. He visto este tipo de patrón varias veces a lo largo de los problemas aquí, específicamente con el enrutador.
Hay 3 soluciones a este problema desde el lado del usuario y ninguna de ellas es un gran DX.
React.forwardRef
. Esto puede ser muy repetitivodiv
, span
, a
, etc.router.push
Independientemente de la solución que utilice, todas son extrañas y requieren comentarios vinculados a este problema o los documentos para explicar a los compañeros de trabajo / colaboradores por qué es necesario para evitar la eliminación / limpieza accidental.
Creo que este tema debería reabrirse para su discusión.
Comentario más útil
Envuelva todos los componentes funcionales utilizados dentro de un
Link
manualmente ? ¿No debería haber una solución más fácil y menos repetitiva para esto? ¿Al menos algo como<Link href="/" forwardRef>...</Link>
?