Created
December 5, 2018 12:23
-
-
Save emyann/e98c2e46b609965b067d044ca3114766 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Router from 'next/router'; | |
import { format, resolve, parse } from 'url'; | |
import Link from 'next/link'; | |
import PropTypes, { exact } from 'prop-types'; | |
import { execOnce, warn } from 'next/dist/lib/utils'; | |
import { Component } from 'react'; | |
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); | |
// get component reference | |
const Component: any = await Router.prefetch(parsedHref); | |
// fetch the component props | |
// and cache locally, handled within getInitialProps | |
if (Component && Component.getInitialProps) { | |
const ctx = { pathname: href, query, isVirtualCall: true }; | |
await Component.getInitialProps(ctx); | |
} | |
}; | |
export interface IExtendedLink extends Link { | |
prefetch?: boolean; | |
withData?: boolean; | |
href: string | object; | |
} | |
export class ExtendedLink<T extends IExtendedLink> extends Component<T, {}> {} | |
// extend default next/link to customize the prefetch behaviour | |
export class LinkWithData extends ExtendedLink<IExtendedLink> { | |
// 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(); | |
// } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment