-
Notifications
You must be signed in to change notification settings - Fork 26k
/
link.js
70 lines (59 loc) · 2.15 KB
/
link.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import PropTypes from 'prop-types'
import Link from 'next/link'
import Router from 'next/router'
import { execOnce, warn } from 'next/dist/lib/utils'
import exact from 'prop-types-exact'
import { format, resolve, parse } from 'url'
export const prefetch = async href => {
// if we're running server side do nothing
if (typeof window === 'undefined') return
const url = typeof href !== 'string' ? format(href) : href
const parsedHref = resolve(window.location.pathname, url)
const { query, pathname } = typeof href !== 'string' ? href : parse(url, true)
const Component = await Router.prefetch(parsedHref)
// if Component exists and has getInitialProps
// fetch the component props (the component should save it in cache)
if (Component && Component.getInitialProps) {
const ctx = { pathname, query, isVirtualCall: true }
await Component.getInitialProps(ctx)
}
}
// extend default next/link to customize the prefetch behaviour
export default class LinkWithData extends Link {
// re defined Link propTypes to add `withData`
static propTypes = exact({
href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
prefetch: PropTypes.bool,
replace: PropTypes.bool,
shallow: PropTypes.bool,
passHref: PropTypes.bool,
scroll: PropTypes.bool,
children: PropTypes.oneOfType([
PropTypes.element,
(props, propName) => {
const value = props[propName]
if (typeof value === 'string') {
execOnce(warn)(
`Warning: You're using a string directly inside <Link>. This usage has been deprecated. Please add an <a> tag as child of <Link>`
)
}
return null
},
]).isRequired,
withData: PropTypes.bool, // our custom prop
})
// our custom prefetch method
async prefetch() {
// if the prefetch prop is not defined do nothing
if (!this.props.prefetch) return
// if withData prop is defined
// prefetch with data
// otherwise just prefetch the page
if (this.props.withData) {
prefetch(this.props.href)
} else {
super.prefetch()
}
}
}