[RFC] useLink
See original GitHub issueGoals
- Have a dependency graph of pages that depend on each other at build time for smart bundling optimizations
- Smaller runtime for linking to other pages
- Getting rid of
cloneElement - Easier to understand API, no more
hrefvsas - Being able to lint for links that we know at build time will always 404
- Replace
next/linkbut retaining backwards compatibility with it. - Easier to understand dynamic routing, as there’s a distinction between the page being rendered and the url.
- Get rid of
buildIdin the page file url to improve long-term caching.
API
Simple usage:
// pages/index.js
import { useLink } from 'next/link'
function HomePage() {
const AboutLink = useLink('/about', () => import('./about'))
return <>
Go to about page
<AboutLink>About</AboutLink>
</>
}
So what does useLink return?
-
An enhanced
<a>component withhref,onClickandrefset -
Automatically prefetches based on viewport
-
import()allows linters to throw when the file doesn’t exist (TS, eslint etc) -
You no longer have to write
<a>inside of<Link>
Alternatives
An alternative API that involves code-generation and is harder to type using TypeScript would be:
// pages/index.js
import { A as AboutLink } from './about'
function HomePage() {
return <>
Go to about page
<AboutLink>About</AboutLink>
</>
}
It would give the same linting / 404 detection benefits as the import API, we’d abstract it away from the user using code generation.
One issue that was raised by @lydiahallie is that creating a navbar would look like this:
const HomeLink = useLink('/', () => import('./index'))
const BlogLink = useLink('/blog', () => import('./blog'))
const BlogHelloWorldLink = useLink('/blog/hello-world', () => import('./blog/hello-world'))
const SupportLink = useLink('/support', () => import('./support'))
const SomethingElseLink = useLink('/something-else', () => import('./something-else'))
const AboutLink = useLink('/about', () => import('./about')) // Copied as filler to give same effect
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
const AboutLink = useLink('/about', () => import('./about'))
The solution for doing something like that might be using returned hook value:
const links = [
useLink('/', () => import('./index')),
useLink('/blog', () => import('./blog')),
useLink('/blog/hello-world', () => import('./blog/hello-world')),
useLink('/support', () => import('./support')),
useLink('/something-else', () => import('./something-else')),
// etc
]
Issue Analytics
- State:
- Created 4 years ago
- Reactions:23
- Comments:20 (15 by maintainers)
Top Results From Across the Web
RFC 2757: Long Thin Networks
A better approach is to use link-layer mechanisms such as FEC, retransmissions, and so on in order to improve the characteristics of the...
Read more >Comments on NWG/RFC 33 and 36 - IETF
This was referred to in RFC #33 as "switch". ... Thus, except for the RFC command, all commands can use link numbers and...
Read more >RFC du Jour (@rfcdujour) / Twitter
#RFC9339 [NEW] This document specifies the extensions to OSPF that enable a router to use Link-Local Signaling (LLS) to signal the metric that...
Read more >Link-local address - Wikipedia
S. Cheshire; B. Aboba; E. Guttma (May 2005). Dynamic Configuration of IPv4 Link-Local Addresses. The Internet Society. doi:10.17487/RFC3927. RFC 3927.
Read more >RFC 9339: - The RFC Archive
Permanent link to RFC 9339 ... Show other RFCs mentioning RFC 9339 ... to OSPF that enable a router to use Link-Local Signaling...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I love the idea of using a hook API for links. One of the most awkward APIs in Next is the way the links work. They are:
I’d suggest that the goal of the link API should be:
For example, in use-next-route I used this API:
This lets me decouple the styled links from next functionality. My projects will usually have a set of low-level UI components. Let’s say I’m using styled-components:
or if I want a button click to trigger a navigation, the API stays the same:
or if I want to navigate on a form submission:
There’s also the problem wanting to pass in parameters. You can do this when you create the link, just like in
Router.push:or you can pass in params when you call
navigate, for times when you don’t know what the parameters are during render:One benefit of doing it this way is you can pull out all of your routes into another file, so you can re-use the logic/parameters, regardless of what type of element is trying to trigger the navigation. In my apps, I have a
hooks/routes.tsfile that contains all of the routes that any component can use:If we were to return an anchor element it limits the ways the route could be used. Let’s say we tried to follow a similar pattern:
This returns an
<a>, but I still want to pass in theprojectIdand I might want to trigger this route after a form submission or on a button click.I’m not too sure how this might affect the ability to create a dependency graph, but maybe we could have a combination of the two:
with the option to pass in parameters:
But it looks a little awkward. I’m not too sure about the mechanics of the
importso I think if I understood that a little more I could suggest something better 😃How would you manage rendering links to unknown routes with this API? For example, in our app we receive a list of menu links from an external CMS. Since our links are dynamic, this proposal wouldn’t work for us. We wouldn’t know which file to import and we would have to use string interpolation in the import statements. From what I understand, interpolated import statements cause a lot more code to be shipped to the client than expected (Webpack has to bundle every possible match). Here’s an example to illustrate the issue I’m describing: