Update dynamic types and tests.

This commit is contained in:
João Vieira
2018-09-25 13:35:22 +01:00
parent b9c03395c0
commit 43fb400ad7
3 changed files with 100 additions and 43 deletions

View File

@@ -1,29 +1,48 @@
import * as React from "react";
import {
LoadableComponent,
CommonOptions as LoadableOptions,
LoadingComponentProps as LoadableLoadingComponentProps
} from "react-loadable";
export interface DynamicOptions<TCProps, TLProps> {
loading?: React.ComponentType<TLProps>;
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
type AsyncComponent<P> = Promise<React.ComponentType<P>>;
type AsyncComponentLoader<P> = () => AsyncComponent<P>;
interface ModuleMapping {
[moduleName: string]: AsyncComponent<any>;
}
interface LoadedModuleMapping {
[moduleName: string]: React.ComponentType<any>;
}
interface NextDynamicOptions<P = {}> extends Omit<LoadableOptions, "loading" | "modules"> {
modules?: () => ModuleMapping; // overridden
loading?: LoadableOptions["loading"]; // optional
loader?: AsyncComponentLoader<P>; // optional, overriden
render?: (props: P, loaded: LoadedModuleMapping) => React.ReactNode; // optional, overriden
ssr?: boolean;
modules?(
props: TCProps & TLProps,
): { [key: string]: Promise<React.ComponentType<any>> };
render?(
props: TCProps & TLProps,
modules: { [key: string]: React.ComponentType<any> },
): void;
loadableGenerated?: {
webpack?: any;
modules?: any;
};
}
export class SameLoopPromise<T> extends Promise<T> {
constructor(
executor: (
resolve: (value?: T) => void,
reject: (reason?: any) => void,
) => void,
);
setResult(value: T): void;
setError(value: any): void;
runIfNeeded(): void;
}
export default function<TCProps, TLProps>(
componentPromise: Promise<React.ComponentType<TCProps>>,
options?: DynamicOptions<TCProps, TLProps>,
): React.ComponentType<TCProps & TLProps>;
type DynamicComponent<P> = React.ComponentType<P> & LoadableComponent;
/**
* Overloaded dynamic function.
* https://github.com/zeit/next.js/blob/7.0.0/lib/dynamic.js#L55
*/
declare function dynamic<P = {}>(
options: AsyncComponent<P> | NextDynamicOptions<P>
): DynamicComponent<P>;
declare function dynamic<P = {}>(
asyncModule: AsyncComponent<P>,
options: NextDynamicOptions<P>
): DynamicComponent<P>;
export type LoadingComponentProps = LoadableLoadingComponentProps;
export default dynamic;

View File

@@ -13,9 +13,7 @@
import * as http from "http";
import * as url from "url";
import { Response as NodeResponse } from "node-fetch";
import { SingletonRouter, DefaultQuery, UrlLike } from "./router";
declare namespace next {

View File

@@ -1,25 +1,65 @@
import dynamic, * as d from "next/dynamic";
import * as React from "react";
import dynamic, { LoadingComponentProps } from "next/dynamic";
// typically you'd use this with an esnext-style import() statement, but we'll make do without
interface DynamicComponentProps {
// You'd typically do this via import('./MyComponent')
interface MyComponentProps {
foo: string;
bar: number;
}
async function getComponent() {
return (props: DynamicComponentProps) => (
<div>
I'm an async component! {props.foo} {props.bar}
</div>
);
}
const MyComponent: React.StatelessComponent<MyComponentProps> = () => <div>I'm async!</div>;
const asyncComponent = Promise.resolve(MyComponent);
interface LoadingComponentProps {
baz: boolean;
}
// Examples from
// https://github.com/zeit/next.js/#dynamic-import
const DynamicComponent = dynamic(getComponent(), {
loading: (props: LoadingComponentProps) => <div>Loading! {props.baz}</div>,
const LoadingComponent: React.StatelessComponent<LoadingComponentProps> = ({
isLoading,
error
}) => <p>loading...</p>;
// 1. Basic Usage (Also does SSR)
const DynamicComponent = dynamic(asyncComponent);
const dynamicComponentJSX = <DynamicComponent foo="bar" />;
// 2. With Custom Loading Component
const DynamicComponentWithCustomLoading = dynamic(asyncComponent, {
loading: LoadingComponent
});
const dynamicComponentWithCustomLoadingJSX = <DynamicComponentWithCustomLoading foo="bar" />;
// 3. With No SSR
const DynamicComponentWithNoSSR = dynamic(asyncComponent, {
ssr: false
});
const jsx = <DynamicComponent foo="five" bar={5} baz />;
// 4. With Multiple Modules At Once
const HelloBundle = dynamic<MyComponentProps>({
modules: () => {
const components = {
Hello1: asyncComponent,
Hello2: asyncComponent
};
return components;
},
render: (props, { Hello1, Hello2 }) => (
<div>
<h1>{props.foo}</h1>
<Hello1 />
<Hello2 />
</div>
)
});
const helloBundleJSX = <HelloBundle foo="bar" />;
// 5. With plain Loadable options
const LoadableComponent = dynamic({
loader: () => asyncComponent,
loading: LoadingComponent,
delay: 200,
timeout: 10000
});
// 6. No loading
const DynamicComponentWithNoLoading = dynamic(asyncComponent, {
loading: () => null
});