Skip to content

Commit

Permalink
improvement(usealien): improve result when resolving multiple modules
Browse files Browse the repository at this point in the history
  • Loading branch information
aneurysmjs committed Jan 15, 2020
1 parent 98d2142 commit 4d32e8f
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 26 deletions.
36 changes: 35 additions & 1 deletion src/app/store/config/alienStore/helpers/modules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnyAction } from 'redux';

import { reducer1 } from './reducers';
import { reducer1, reducerA, reducerB } from './reducers';

export const reduxModule = {
reducers: {
Expand All @@ -27,3 +27,37 @@ export const reduxModuleNoReducers = {
}),
},
};

export const reduxModuleA = {
reducers: {
stateA: reducerA,
},
actions: {
actionA: (): AnyAction => ({
type: 'ACTION_A',
payload: {
name: 'Джеро',
},
}),
},
selectors: {
selectorA: ({ sliceA }) => sliceA,
},
};

export const reduxModuleB = {
reducers: {
stateB: reducerB,
},
actions: {
actionB: (): AnyAction => ({
type: 'ACTION_B',
payload: {
name: 'Джеро',
},
}),
},
selectors: {
selectorB: ({ sliceA }) => sliceA,
},
};
16 changes: 15 additions & 1 deletion src/app/store/config/alienStore/helpers/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnyAction } from 'redux';

export const initialReducer = {
state: (s = 'default state', action: AnyAction): string => {
someState: (s = 'default state', action: AnyAction): string => {
if (action.type === 'INIT') {
return 'init value';
}
Expand All @@ -22,3 +22,17 @@ export const reducer2 = (s = 'reducer2 default state', action: AnyAction): strin
}
return s;
};

export const reducerA = (s = 'reducerA default state', action: AnyAction): string => {
if (action.type === 'ACTION_A') {
return 'reducerA value';
}
return s;
};

export const reducerB = (s = 'reducerB default state', action: AnyAction): string => {
if (action.type === 'ACTION_B') {
return 'reducerB value';
}
return s;
};
27 changes: 19 additions & 8 deletions src/app/store/config/alienStore/useAlien.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import alien from './alien';

import useAlien from './useAlien';

import { reduxModule, reduxModuleNoReducers } from './helpers/modules';
import { reduxModule, reduxModuleNoReducers, reduxModuleA, reduxModuleB } from './helpers/modules';
import { withProvider, WrapperType } from './helpers/withProvider';

const WRONG_COMPONENT_PATH = './some/wrong/component/path';
Expand All @@ -25,14 +25,21 @@ beforeEach(() => {
*/
describe('useAlien', () => {
type ReduxModuleType = Promise<typeof reduxModule>;
type ReduxModuleAType = Promise<typeof reduxModuleA>;
type ReduxModuleBType = Promise<typeof reduxModuleB>;

it('should render "null" at first and then resolve the module', async () => {
const alienModule = {
id: 'some-alien-module',
getModule: (): ReduxModuleType => Promise.resolve(reduxModule),
it('should render "null" at first and then resolve each module', async () => {
const alienModuleA = {
id: 'alien-module-a',
getModule: (): ReduxModuleAType => Promise.resolve(reduxModuleA),
};

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
const alienModuleB = {
id: 'alien-module-b',
getModule: (): ReduxModuleBType => Promise.resolve(reduxModuleB),
};

const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModuleA, alienModuleB]), {
wrapper,
});

Expand All @@ -43,12 +50,16 @@ describe('useAlien', () => {
await waitForNextUpdate();

expect(store.getState()).toEqual({
state1: 'reducer1 default state',
stateA: 'reducerA default state',
stateB: 'reducerB default state',
});

expect(result.current).toHaveProperty('actions');
// @ts-ignore - 'actions' is always part of the result
expect(result.current.actions).toStrictEqual(reduxModule.actions);
expect(result.current.actions).toStrictEqual({
...reduxModuleA.actions,
...reduxModuleB.actions,
});
});

it('should call cb when unmounting', async () => {
Expand Down
44 changes: 28 additions & 16 deletions src/app/store/config/alienStore/useAlien.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function useAlien<T>(
const {
alienManager: { injectReducers, rootReducer },
} = store;
const [alien, setAlien] = useState<AlienResult | null>(null);
const [alien, setAlien] = useState<[AlienResult] | null>(null);

useEffect(() => {
(async (): Promise<void> => {
Expand All @@ -59,21 +59,33 @@ function useAlien<T>(

const resolvedModules = await Promise.all(promises);

resolvedModules.forEach(alienModule => {
const { reducers, actions, selectors } = alienModule;

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]);
});

store.replaceReducer(rootReducer);

setAlien({ actions, selectors });
});
const result = resolvedModules.reduce(
(acc, { reducers, actions, selectors }: ReduxModule<T>) => {
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]);
});

store.replaceReducer(rootReducer);

return {
actions: { ...acc.actions, ...actions },
// adds the "selectors" property if any exists
...(selectors && {
selectors: {
...acc.selectors,
...selectors,
},
}),
};
},
{},
);

setAlien(result);
} catch (err) {
setAlien(err);
}
Expand Down

0 comments on commit 4d32e8f

Please sign in to comment.