From c2b40c18c15a14e7b190dd5caf96705f06a703d2 Mon Sep 17 00:00:00 2001 From: Ben Saufley Date: Fri, 15 Jun 2018 13:36:18 -0400 Subject: [PATCH] [next] Update router types --- types/next/router.d.ts | 40 +++++++++------ types/next/test/next-router-tests.tsx | 72 ++++++++++++++++++--------- 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/types/next/router.d.ts b/types/next/router.d.ts index 544c29bc7e..4eb24dc3ff 100644 --- a/types/next/router.d.ts +++ b/types/next/router.d.ts @@ -8,12 +8,11 @@ export interface EventChangeOptions { [key: string]: any; } +export type PopStateCallback = (state: any) => boolean | undefined; + export type RouterCallback = () => void; export interface RouterProps { - // router properties - readonly components: { - [key: string]: { Component: React.ComponentType; err: any }; - }; + // url property fields readonly pathname: string; readonly route: string; readonly asPath?: string; @@ -27,39 +26,50 @@ export interface RouterProps { | string[]; }; - // router methods - reload(route: string): Promise; + // property fields + readonly components: { + [key: string]: { Component: React.ComponentType; err: any }; + }; + + // core method fields back(): void; + beforePopState(cb: PopStateCallback): boolean; + prefetch(url: string): Promise>; push( url: string | UrlLike, as?: string | UrlLike, options?: EventChangeOptions, ): Promise; + reload(route: string): Promise; replace( url: string | UrlLike, as?: string | UrlLike, options?: EventChangeOptions, ): Promise; - prefetch(url: string): Promise>; - // router events + // events onAppUpdated?(nextRoute: string): void; - onRouteChangeStart?(url: string): void; onBeforeHistoryChange?(as: string): void; + onHashChangeStart?(url: string): void; + onHashChangeComplete?(url: string): void; onRouteChangeComplete?(url: string): void; onRouteChangeError?(error: any, url: string): void; + onRouteChangeStart?(url: string): void; } -export interface SingletonRouter { - router: RouterProps; +export interface SingletonRouter extends RouterProps { + router: RouterProps | null; readyCallbacks: RouterCallback[]; ready(cb: RouterCallback): void; } +export interface WithRouterProps { + router: SingletonRouter; +} + export function withRouter( - Component: React.ComponentType, + Component: React.ComponentType, ): React.ComponentType; -export const Singleton: SingletonRouter; -export type ImperativeRouter = RouterProps; -export default Singleton; +declare const Router: SingletonRouter; +export default Router; diff --git a/types/next/test/next-router-tests.tsx b/types/next/test/next-router-tests.tsx index 822b9b8e6f..70c41081bd 100644 --- a/types/next/test/next-router-tests.tsx +++ b/types/next/test/next-router-tests.tsx @@ -1,4 +1,4 @@ -import Router, * as r from "next/router"; +import Router, { withRouter, WithRouterProps } from "next/router"; import * as React from "react"; import * as qs from "querystring"; @@ -13,8 +13,8 @@ Router.ready(() => { // Access readonly properties of the router. -Object.keys(Router.router.components).forEach(key => { - const c = Router.router.components[key]; +Object.keys(Router.components).forEach(key => { + const c = Router.components[key]; c.err.isAnAny; return ; @@ -26,52 +26,78 @@ function split(routeLike: string) { }); } -if (Router.router.asPath) { - split(Router.router.asPath); - split(Router.router.asPath); +if (Router.asPath) { + split(Router.asPath); + split(Router.asPath); } -split(Router.router.pathname); +split(Router.pathname); -const query = `?${qs.stringify(Router.router.query)}`; +const query = `?${qs.stringify(Router.query)}`; // Assign some callback methods. -Router.router.onAppUpdated = (nextRoute: string) => console.log(nextRoute); -Router.router.onRouteChangeStart = (url: string) => +Router.onAppUpdated = (nextRoute: string) => console.log(nextRoute); +Router.onRouteChangeStart = (url: string) => console.log("Route is starting to change.", url); -Router.router.onBeforeHistoryChange = (as: string) => +Router.onBeforeHistoryChange = (as: string) => console.log("History hasn't changed yet.", as); -Router.router.onRouteChangeComplete = (url: string) => +Router.onRouteChangeComplete = (url: string) => console.log("Route chaneg is complete.", url); -Router.router.onRouteChangeError = (err: any, url: string) => +Router.onRouteChangeError = (err: any, url: string) => console.log("Route is starting to change.", url, err); // Call methods on the router itself. -Router.router.reload("/route").then(() => console.log("route was reloaded")); -Router.router.back(); +Router.reload("/route").then(() => console.log("route was reloaded")); +Router.back(); +Router.beforePopState(({ url }) => !!url); -Router.router.push("/route").then((success: boolean) => +Router.push("/route").then((success: boolean) => console.log("route push success: ", success), ); -Router.router.push("/route", "/asRoute").then((success: boolean) => +Router.push("/route", "/asRoute").then((success: boolean) => console.log("route push success: ", success), ); -Router.router.push("/route", "/asRoute", { shallow: false }).then((success: boolean) => +Router.push("/route", "/asRoute", { shallow: false }).then((success: boolean) => console.log("route push success: ", success), ); -Router.router.replace("/route").then((success: boolean) => +Router.replace("/route").then((success: boolean) => console.log("route replace success: ", success), ); -Router.router.replace("/route", "/asRoute").then((success: boolean) => +Router.replace("/route", "/asRoute").then((success: boolean) => console.log("route replace success: ", success), ); -Router.router.replace("/route", "/asRoute", { +Router.replace("/route", "/asRoute", { shallow: false, }).then((success: boolean) => console.log("route replace success: ", success)); -Router.router.prefetch("/route").then(Component => { +Router.prefetch("/route").then(Component => { const element = ; }); -r.withRouter(props =>
); +interface TestComponentProps { + testValue: string; +} + +class TestComponent extends React.Component { + state = { ready: false }; + + constructor(props: TestComponentProps & WithRouterProps) { + super(props); + props.router.ready(() => { + this.setState({ ready: true }); + }); + } + + render() { + return ( +
+

{this.state.ready ? 'Ready' : 'Not Ready'}

+

Route: {this.props.router.route}

+

Another prop: {this.props.testValue}

+
+ ); + } +} + +withRouter(TestComponent);