UNPKG

next

Version:

The React Framework

169 lines (168 loc) 5.87 kB
/* global window */ import React from 'react'; import Router from '../shared/lib/router/router'; import { RouterContext } from '../shared/lib/router-context.shared-runtime'; import isError from '../lib/is-error'; export { Router }; const singletonRouter = { router: null, readyCallbacks: [], ready (callback) { if (this.router) return callback(); if (typeof window !== 'undefined') { this.readyCallbacks.push(callback); } } }; // Create public properties and methods of the router in the singletonRouter const urlPropertyFields = [ 'pathname', 'route', 'query', 'asPath', 'components', 'isFallback', 'basePath', 'locale', 'locales', 'defaultLocale', 'isReady', 'isPreview', 'isLocaleDomain', 'domainLocales' ]; const routerEvents = [ 'routeChangeStart', 'beforeHistoryChange', 'routeChangeComplete', 'routeChangeError', 'hashChangeStart', 'hashChangeComplete' ]; const coreMethodFields = [ 'push', 'replace', 'reload', 'back', 'prefetch', 'beforePopState' ]; // Events is a static property on the router, the router doesn't have to be initialized to use it Object.defineProperty(singletonRouter, 'events', { get () { return Router.events; } }); function getRouter() { if (!singletonRouter.router) { const message = 'No router instance found.\n' + 'You should only use "next/router" on the client side of your app.\n'; throw Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", { value: "E394", enumerable: false, configurable: true }); } return singletonRouter.router; } urlPropertyFields.forEach((field)=>{ // Here we need to use Object.defineProperty because we need to return // the property assigned to the actual router // The value might get changed as we change routes and this is the // proper way to access it Object.defineProperty(singletonRouter, field, { get () { const router = getRouter(); return router[field]; } }); }); coreMethodFields.forEach((field)=>{ // We don't really know the types here, so we add them later instead ; singletonRouter[field] = function() { for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ args[_key] = arguments[_key]; } const router = getRouter(); return router[field](...args); }; }); routerEvents.forEach((event)=>{ singletonRouter.ready(()=>{ Router.events.on(event, function() { for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ args[_key] = arguments[_key]; } const eventField = "on" + event.charAt(0).toUpperCase() + event.substring(1); const _singletonRouter = singletonRouter; if (_singletonRouter[eventField]) { try { _singletonRouter[eventField](...args); } catch (err) { console.error("Error when running the Router event: " + eventField); console.error(isError(err) ? err.message + "\n" + err.stack : err + ''); } } }); }); }); // Export the singletonRouter and this is the public API. export default singletonRouter; // Reexport the withRouter HOC export { default as withRouter } from './with-router'; /** * This hook gives access the [router object](https://nextjs.org/docs/pages/api-reference/functions/use-router#router-object) * inside the [Pages Router](https://nextjs.org/docs/pages/building-your-application). * * Read more: [Next.js Docs: `useRouter`](https://nextjs.org/docs/pages/api-reference/functions/use-router) */ export function useRouter() { const router = React.useContext(RouterContext); if (!router) { throw Object.defineProperty(new Error('NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted'), "__NEXT_ERROR_CODE", { value: "E509", enumerable: false, configurable: true }); } return router; } /** * Create a router and assign it as the singleton instance. * This is used in client side when we are initializing the app. * This should **not** be used inside the server. * @internal */ export function createRouter() { for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ args[_key] = arguments[_key]; } singletonRouter.router = new Router(...args); singletonRouter.readyCallbacks.forEach((cb)=>cb()); singletonRouter.readyCallbacks = []; return singletonRouter.router; } /** * This function is used to create the `withRouter` router instance * @internal */ export function makePublicRouterInstance(router) { const scopedRouter = router; const instance = {}; for (const property of urlPropertyFields){ if (typeof scopedRouter[property] === 'object') { instance[property] = Object.assign(Array.isArray(scopedRouter[property]) ? [] : {}, scopedRouter[property]) // makes sure query is not stateful ; continue; } instance[property] = scopedRouter[property]; } // Events is a static property on the router, the router doesn't have to be initialized to use it instance.events = Router.events; coreMethodFields.forEach((field)=>{ instance[field] = function() { for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ args[_key] = arguments[_key]; } return scopedRouter[field](...args); }; }); return instance; } //# sourceMappingURL=router.js.map