mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Extend with-data-prefetch to handle advanced use cases (#3525)
This commit is contained in:
parent
8dd8e200e0
commit
c40f184a6a
|
@ -5,6 +5,34 @@ 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 { pathname } = window.location
|
||||
|
||||
const parsedHref = resolve(pathname, url)
|
||||
|
||||
const { query } =
|
||||
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: href, 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`
|
||||
|
@ -33,32 +61,16 @@ export default class LinkWithData extends Link {
|
|||
|
||||
// our custom prefetch method
|
||||
async prefetch () {
|
||||
// if the prefetch prop is not defined or
|
||||
// we're running server side do nothing
|
||||
// if the prefetch prop is not defined do nothing
|
||||
if (!this.props.prefetch) return
|
||||
if (typeof window === 'undefined') return
|
||||
|
||||
const url =
|
||||
typeof this.props.href !== 'string'
|
||||
? format(this.props.href)
|
||||
: this.props.href
|
||||
|
||||
const { pathname } = window.location
|
||||
|
||||
const href = resolve(pathname, url)
|
||||
|
||||
const { query } =
|
||||
typeof this.props.href !== 'string'
|
||||
? this.props.href
|
||||
: parse(url, true)
|
||||
|
||||
const Component = await Router.prefetch(href)
|
||||
|
||||
// if withData prop is defined, Component exists and has getInitialProps
|
||||
// fetch the component props (the component should save it in cache)
|
||||
if (this.props.withData && Component && Component.getInitialProps) {
|
||||
const ctx = { pathname: href, query, isVirtualCall: true }
|
||||
await Component.getInitialProps(ctx)
|
||||
// if withData prop is defined
|
||||
// prefetch with data
|
||||
// otherwise just prefetch the page
|
||||
if (this.props.withData) {
|
||||
prefetch(this.props.href)
|
||||
} else {
|
||||
super.prefetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Link from '../components/link'
|
||||
import Link, { prefetch } from '../components/link'
|
||||
|
||||
// we just render a list of 3 articles having 2 with prefetched data
|
||||
export default () => (
|
||||
|
@ -16,8 +16,8 @@ export default () => (
|
|||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href='/article?id=3' prefetch withData>
|
||||
<a>Article 3</a>
|
||||
<Link href='/article?id=3' >
|
||||
<a onMouseOver={e => prefetch('/article?id=3')} >Article 3</a>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in a new issue