When using next/link and passing a function component as the child, it does a full server side render and page refresh on click rather than a client side routing.
The following link works:
import Link from 'next/link';
import React from 'react';
const TestThing = () => (
<Link as="/en/checkout" href="/[locale]/checkout" passHref>
<a>Checkout</a>
</Link
);
The following does a SSR load rather than client side on click:
const Button = ({ children }) => (
<a className="button">
{children}
</a>
);
const TestThing = () => (
<Link as="/en/checkout" href="/[locale]/checkout" passHref>
<Button>Checkout</Button>
</Link
);
I've seen a new addition to the README in v9.0.4-canary.2:
Note: if passing a functional component as a child of <Link> you will need to wrap it in React.forwardRef
I've tried various methods of adding a ref including forwardRef on my Button component but nothing seems to work. Perhaps I'm doing it wrong. Can someone confirm whether this is a bug with the link component or just provide an example of how this should look with the correct ref setup? I feel like the docs are not clear on this.
Guess your button component should simply relay href to <a>:
-const Button = ({ children }) => (
- <a className="button">
+const Button = ({ children, href }) => (
+ <a className="button" href={href}>
{children}
</a>
);
It might be a good idea to pass title down too.
Hi, the syntax to use React.forwardRef with a function component would be
import React from "react";
import Link from "next/link";
const Button = React.forwardRef(({ children, href, onClick }, ref) => (
<a
ref={ref}
href={href}
onClick={onClick}
className="button"
>
{children}
</a>
));
const TestThing = () => (
<Link href="/" passHref>
<Button>Checkout</Button>
</Link>
);
export default TestThing;
For more information on forwardRef see the React docs here. If you are still having trouble with this feel free to reply with additional info
@ijjk Thank you but I can confirm this is not working. Same problem where it creates the anchor with the correct href but clicking it does a SSR rather than client side route change. Since I am correctly applying the forwardRef and the link correctly does client side routing when using an anchor tag directly instead of a function component child, I can only assume this is a NextJS bug at the moment. Are we able to re-open this issue?
@caribou-code can you provide a link to a reproduction? We have tests covering forwardRef usage with next/link here so it doesn't seem as likely to be related to that. There might be something else not lining up which can be seen easier with a reproduction
@ijjk Ok I've discovered I was missing the onClick prop in my Button component and that's what was breaking it (I realise now you had that in your example above). I just assumed I didn't need it because I'm not using click events or useRouter and I'm only concerned with the as and href values on a next/link. I feel like this definitely needs documenting somewhere.
Bug report
Describe the bug
When using next/link and passing a function component as the child, it does a full server side render and page refresh on click rather than a client side routing.
To Reproduce
The following link works:
import Link from 'next/link'; import React from 'react'; const TestThing = () => ( <Link as="/en/checkout" href="/[locale]/checkout" passHref> <a>Checkout</a> </Link );The following does a SSR load rather than client side on click:
const Button = ({ children }) => ( <a className="button"> {children} </a> ); const TestThing = () => ( <Link as="/en/checkout" href="/[locale]/checkout" passHref> <Button>Checkout</Button> </Link );Additional context
I've seen a new addition to the README in v9.0.4-canary.2:
Note: if passing a functional component as a child of <Link> you will need to wrap it in React.forwardRefI've tried various methods of adding a ref including forwardRef on my Button component but nothing seems to work. Perhaps I'm doing it wrong. Can someone confirm whether this is a bug with the link component or just provide an example of how this should look with the correct ref setup? I feel like the docs are not clear on this.
For this routing to work without refresh how does your pages look lilke?
e.g. pages -> [locale].js or is it something else
Guess your button component should simply relay
hrefto<a>:-const Button = ({ children }) => ( - <a className="button"> +const Button = ({ children, href }) => ( + <a className="button" href={href}> {children} </a> );It might be a good idea to pass
titledown too.
I was dealing with this issue exactly--and this solved my problem!
Now I'm wondering why Next.js wants navigation links to be written like this?
Most helpful comment
Hi, the syntax to use
React.forwardRefwith a function component would beFor more information on
forwardRefsee the React docs here. If you are still having trouble with this feel free to reply with additional info