Skip to content

Commit

Permalink
feat(uselazy): handle multiple imports
Browse files Browse the repository at this point in the history
now it can handle and array of import promises
  • Loading branch information
aneurysmjs committed Oct 28, 2019
1 parent 4e1be8f commit 57741bf
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const App = () => {
Buy me a beer
</button>

{/* at first the condition is false */}
{/* at first is null the condition is false */}
{SomeComponent && <SomeComponent />}
</div>
);
Expand Down
6 changes: 6 additions & 0 deletions src/__test__/AnotherExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React, { ReactElement } from 'react';

// eslint-disable-next-line react/no-unescaped-entities
const AnotherExample = (): ReactElement => <div> I've no idea what I'm doing </div>;

export default AnotherExample;
26 changes: 24 additions & 2 deletions src/__test__/useLazy.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
/* eslint-disable @typescript-eslint/indent */
/* eslint-disable @typescript-eslint/ban-ts-ignore */
import { renderHook } from '@testing-library/react-hooks';

import useLazy from '../useLazy';

type DynamicModule = () => Promise<typeof import('./Example')>;
type ExampleModule = () => Promise<typeof import('./Example')>;

const getModule: DynamicModule = () => import('./Example');
type GetModules = () => Array<
Promise<typeof import('./Example') | typeof import('./AnotherExample')>
>;
const getModule: ExampleModule = () => import('./Example');
const getModules: GetModules = () => [import('./Example'), import('./AnotherExample')];

describe('LazyComponent', () => {
it('should render "null" at first and then resolve promise', async () => {
Expand All @@ -29,6 +34,23 @@ describe('LazyComponent', () => {
expect(typeof result.current).toBe('function');
expect(handleFinally).toHaveBeenCalledTimes(1);
});

it('should now how to handle and array of promises', async () => {
const handleFinally = jest.fn();
const { result, waitForNextUpdate } = renderHook(() =>
// @ts-ignore
useLazy(getModules, true, handleFinally),
);
expect(result.current).toEqual(null);

await waitForNextUpdate();

expect(Array.isArray(result.current)).toBe(true);
// @ts-ignore
expect(result.current.every(f => typeof f === 'function')).toBe(true);
expect(handleFinally).toHaveBeenCalledTimes(1);
});

it('should throw', async () => {
// @ts-ignore - just for testing purposes
type WrongModule = typeof import('./wrong/Example');
Expand Down
18 changes: 14 additions & 4 deletions src/useLazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { useState, useEffect } from 'react';

import handleThrow from './utils/handleThrow';

type GetModuleType<P> = () => Promise<{ default: () => P }> | Array<Promise<{ default: () => P }>>;

function useLazy<P>(
getModule: () => Promise<{ default: () => P }>,
getModule: GetModuleType<P>,
cond = false,
onFynally: () => void = (): void => {},
): (() => P) | null {
const [AsyncModule, setAsyncModule] = useState<(() => P) | null>(null);
): (() => P) | Array<() => P> | null {
const [AsyncModule, setAsyncModule] = useState<(() => P) | Array<() => P> | null>(null);

useEffect(() => {
(async (): Promise<void> => {
Expand All @@ -16,7 +18,15 @@ function useLazy<P>(
return;
}
const module = await getModule();
setAsyncModule(() => module.default);

if (module instanceof Array) {
const modules = await Promise.all(module);
setAsyncModule(modules.map(m => m.default));
}

if ('default' in module) {
setAsyncModule(() => module.default);
}
} catch (err) {
setAsyncModule(err);
} finally {
Expand Down

0 comments on commit 57741bf

Please sign in to comment.