From 98d2142b5ab35f5bbac128ddda225ef743035943 Mon Sep 17 00:00:00 2001 From: jero Date: Mon, 13 Jan 2020 23:57:50 +0300 Subject: [PATCH] feat(usealien): receive and array of alienModules instead of a single module this allow register multiple modules is some of then depend of some one #43 --- .../store/config/alienStore/useAlien.test.tsx | 10 ++--- src/app/store/config/alienStore/useAlien.tsx | 40 ++++++++++++------- .../config/alienStore/withAlien.test.tsx | 2 +- src/app/store/config/alienStore/withAlien.tsx | 2 +- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/app/store/config/alienStore/useAlien.test.tsx b/src/app/store/config/alienStore/useAlien.test.tsx index bf2b89de..9f57fb0f 100644 --- a/src/app/store/config/alienStore/useAlien.test.tsx +++ b/src/app/store/config/alienStore/useAlien.test.tsx @@ -32,7 +32,7 @@ describe('useAlien', () => { getModule: (): ReduxModuleType => Promise.resolve(reduxModule), }; - const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), { + const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), { wrapper, }); @@ -59,7 +59,7 @@ describe('useAlien', () => { const cb = jest.fn(); - const { result, waitForNextUpdate, unmount } = renderHook(() => useAlien(alienModule, cb), { + const { result, waitForNextUpdate, unmount } = renderHook(() => useAlien([alienModule], cb), { wrapper, }); @@ -88,7 +88,7 @@ describe('useAlien', () => { }; // @ts-ignore - "id" doesn't exist for testing purposes - const { result } = renderHook(() => useAlien(alienModule), { + const { result } = renderHook(() => useAlien([alienModule]), { wrapper, }); @@ -107,7 +107,7 @@ describe('useAlien', () => { getModule: (): ReduxModuleType => import(WRONG_COMPONENT_PATH), }; - const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), { + const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), { wrapper, }); @@ -132,7 +132,7 @@ describe('useAlien', () => { getModule: (): ReduxModuleNoReducersType => Promise.resolve(reduxModuleNoReducers), }; - const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), { + const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), { wrapper, }); diff --git a/src/app/store/config/alienStore/useAlien.tsx b/src/app/store/config/alienStore/useAlien.tsx index 253451f9..e1352321 100644 --- a/src/app/store/config/alienStore/useAlien.tsx +++ b/src/app/store/config/alienStore/useAlien.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { Reducer, AnyAction, ActionCreator } from 'redux'; import { useStore } from 'react-redux'; -import { isEmpty, isNil } from 'ramda'; +import { isEmpty, isNil, anyPass, any } from 'ramda'; import { AlienStore } from './alien'; @@ -13,7 +13,7 @@ export interface ReduxModule { [K: string]: ActionCreator; }; selectors?: { - [K: string]: (state: S) => T; + [K: string]: (state: T) => T; }; } @@ -25,6 +25,8 @@ export interface AlienModule { initialActions?: Array; } +const check: (obj: T) => boolean = anyPass([isNil, isEmpty]); + function errorHandler(errorOrObj: T): T { if (errorOrObj) { // rejection from `import()` for some reason is not and instance of Error @@ -36,8 +38,11 @@ function errorHandler(errorOrObj: T): T { return errorOrObj; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function useAlien(alienModule: AlienModule, cb: () => void = () => {}): AlienResult | null { +function useAlien( + alienModules: [AlienModule], + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + cb: () => void = () => {}, +): AlienResult | null { const store = useStore() as AlienStore; const { alienManager: { injectReducers, rootReducer }, @@ -47,23 +52,28 @@ function useAlien(alienModule: AlienModule, cb: () => void = () => {}): Al useEffect(() => { (async (): Promise => { try { - if (isNil(alienModule.id) || isEmpty(alienModule.id)) { + if (any(({ id }) => check(id), alienModules)) { throw new Error('Alien Module has no id'); } + const promises = alienModules.map(alienModule => alienModule.getModule()); - const { reducers, actions, selectors } = await alienModule.getModule(); + const resolvedModules = await Promise.all(promises); - if (isNil(reducers) || isEmpty(reducers)) { - throw new Error('Redux Module has no reducers'); - } - // is safe here to iterate reducers's keys for reducer injection - Object.keys(reducers).forEach(key => { - injectReducers(key, reducers[key]); - }); + resolvedModules.forEach(alienModule => { + const { reducers, actions, selectors } = alienModule; - store.replaceReducer(rootReducer); + if (check(reducers)) { + throw new Error('Redux Module has no reducers'); + } + // is safe here to iterate reducers's keys for reducer injection + Object.keys(reducers).forEach(key => { + injectReducers(key, reducers[key]); + }); - setAlien({ actions, selectors }); + store.replaceReducer(rootReducer); + + setAlien({ actions, selectors }); + }); } catch (err) { setAlien(err); } diff --git a/src/app/store/config/alienStore/withAlien.test.tsx b/src/app/store/config/alienStore/withAlien.test.tsx index 5d4d354d..7441a3a6 100644 --- a/src/app/store/config/alienStore/withAlien.test.tsx +++ b/src/app/store/config/alienStore/withAlien.test.tsx @@ -27,7 +27,7 @@ describe('test "withAlien"', () => { id: 'with', getModule, }; - const { result, waitForNextUpdate } = renderHook(() => withAlien(Example, alienModule), { + const { result, waitForNextUpdate } = renderHook(() => withAlien(Example, [alienModule]), { wrapper, }); diff --git a/src/app/store/config/alienStore/withAlien.tsx b/src/app/store/config/alienStore/withAlien.tsx index 87764035..0fcab534 100644 --- a/src/app/store/config/alienStore/withAlien.tsx +++ b/src/app/store/config/alienStore/withAlien.tsx @@ -8,7 +8,7 @@ interface WithAlienProps { function WithAlien

( Component: ComponentType

, - alienModule: AlienModule, + alienModule: [AlienModule], ): ReactElement

| null { const alienResult = useAlien(alienModule);