Skip to content

Commit

Permalink
Add documentation comments to lazyResource, lazyComponent, and other …
Browse files Browse the repository at this point in the history
…functions
  • Loading branch information
kyarik committed Nov 28, 2020
1 parent 9e7c2c1 commit 2000458
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
37 changes: 35 additions & 2 deletions src/lazyComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@ const componentResources = new WeakMap<
Resource<{ default: ComponentType<any> }>
>();

/**
* Creates a lazy React component. It's lazy because it will not start loading
* the original component immediately. Instead, it will start loading it only
* when the component is being rendered or when `preloadLazyComponent` is
* called. The component can be rendered at any point; if it has not loaded at
* the time it is rendered, it will suspend.
* @param loader the loader function to load a React component. This is a
* function that returns a dynamic import. The component should be the default
* export of the module that is dynamically imported.
* @param options the resource options.
* @returns a lazy React component that accepts exactly the same props as the
* component being dynamically imported.
*/
export const lazyComponent = <P extends {} = {}>(
componentLoader: () => Promise<{ default: ComponentType<P> }>,
loader: () => Promise<{ default: ComponentType<P> }>,
options?: ResourceOptions,
) => {
const resource = lazyResource(componentLoader, options);
const resource = lazyResource(loader, options);

const LazyComponent = (props: P) => {
resource.load();
Expand All @@ -26,6 +39,18 @@ export const lazyComponent = <P extends {} = {}>(
return LazyComponent;
};

/**
* Preloads a lazy component, i.e., starts loading the lazy component even
* before it is rendered. Good places where to start preloading a component are
* the router and event handlers. Under the hood, this function is just calling
* `Resource#load()` for the component resource, which means that it is
* idempotent - calling it after the first time has no effect. However, If the
* component fails to load and `clearLazyComponentError` is called (or
* `clearResourceErrors`), then calling this method will again begin loading
* the component.
* @param LazyComponent the lazy component returned by `lazyComponent` that we
* want to preload.
*/
export const preloadLazyComponent = (LazyComponent: ComponentType<any>) => {
const resource = componentResources.get(LazyComponent);

Expand All @@ -36,6 +61,14 @@ export const preloadLazyComponent = (LazyComponent: ComponentType<any>) => {
resource.load();
};

/**
* Clears the error for a lazy component that failed to load. This allows
* rendering the component again and calling `preloadLazyComponent` to retry
* loading the component. This function has no effect if the component is still
* loading or if it already loaded successfully.
* @param LazyComponent the lazy component returned by `lazyComponent` for which
* we want to clear the error.
*/
export const clearLazyComponentError = (LazyComponent: ComponentType<any>) => {
const resource = componentResources.get(LazyComponent);

Expand Down
15 changes: 15 additions & 0 deletions src/lazyResource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ import { autoRetryOnRejection } from '../utils/promise/autoRetryOnRejection';

const resourcesWithError = new Set<Resource<unknown>>();

/**
* Creates a lazy resource. It's lazy because it will not start loading the
* resource immediately. Instead, it will start loading it only when the `load`
* method is called. The resource can be read at any point inside a React
* component - if it has not loaded at the time it is called, the component
* will suspend.
* @param loader the loader function to load a resource of type `T`. This is a
* regular function that returns a promise.
* @param options the resource options.
* @returns a resource of type `T`.
*/
export const lazyResource = <T>(
loader: Loader<T>,
options: ResourceOptions = {},
Expand Down Expand Up @@ -78,6 +89,10 @@ export const lazyResource = <T>(
return resource;
};

/**
* Clears the errors for all resources that failed to load. This means that all
* those resource can retry loading by calling the `Resource#load` method.
*/
export const clearResourceErrors = () => {
resourcesWithError.forEach(resource => resource.clearError());

Expand Down

0 comments on commit 2000458

Please sign in to comment.