Skip to content

Instantly share code, notes, and snippets.

@emyann
Created December 5, 2018 12:23
Show Gist options
  • Save emyann/e98c2e46b609965b067d044ca3114766 to your computer and use it in GitHub Desktop.
Save emyann/e98c2e46b609965b067d044ca3114766 to your computer and use it in GitHub Desktop.
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