Skip to content

Commit

Permalink
feat(alienstore): add useAlienModule hook
Browse files Browse the repository at this point in the history
import dynamically a Redux module and inject its reducers

improves #43
  • Loading branch information
aneurysmjs committed Oct 17, 2019
1 parent 0b90696 commit bce2d50
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
33 changes: 32 additions & 1 deletion src/app/store/config/alienStore/alienStore.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable @typescript-eslint/ban-ts-ignore, import/no-named-as-default-member */
import React, { ReactElement } from 'react';
import { createStore as createReduxStore } from 'redux';
import { renderHook, act, RenderHookResult } from '@testing-library/react-hooks';
import { createStore as createReduxStore, AnyAction } from 'redux';
import alienStore, {
createStore,
reloadStore,
injectReducers,
withStoreModule,
useAlienModule,
} from './alienStore';

describe('Dyno Store', () => {
Expand All @@ -14,6 +16,7 @@ describe('Dyno Store', () => {
expect(alienStore).toHaveProperty('reloadStore');
expect(alienStore).toHaveProperty('injectReducers');
expect(alienStore).toHaveProperty('withStoreModule');
expect(alienStore).toHaveProperty('useAlienModule');
});

it('should create and return a Redux store', () => {
Expand Down Expand Up @@ -81,4 +84,32 @@ describe('Dyno Store', () => {
});
});
});

describe('test "useAlienModule"', () => {
const alienModuleMock = {
actions: {
dummyAction: (): AnyAction => ({
type: 'DUMMY_ACTION',
payload: {
name: 'Джеро',
},
}),
},
};

type AlienModuleType = Promise<{ default: typeof alienModuleMock }>;

const importAlienModule = (): AlienModuleType => Promise.resolve({ default: alienModuleMock });
it('should render "null" at first', async () => {
const store = createStore();
const mockDispatch = jest.spyOn(store, 'dispatch');
let hookRenderer = {} as RenderHookResult<{}, AlienModuleType>;
await act(async () => {
hookRenderer = renderHook(() => useAlienModule(importAlienModule));
});
expect(mockDispatch).toHaveBeenCalledTimes(1);
expect(mockDispatch).toHaveBeenCalledWith({ type: '@@ALIEN_STORE/RELOAD' });
expect(hookRenderer.result.current).toEqual({ default: alienModuleMock });
});
});
});
24 changes: 23 additions & 1 deletion src/app/store/config/alienStore/alienStore.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComponentType } from 'react';
import { ComponentType, useEffect, useState } from 'react';
import {
createStore as createReduxStore,
combineReducers,
Expand Down Expand Up @@ -47,9 +47,31 @@ export async function withStoreModule<P>(
}
}

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

export function useAlienModule<P>(moduleStore: UseAlienModuleImportType<P>): P | null {
const [alienModule, setAlienModule] = useState<P | null>(null);

useEffect(() => {
(async (): Promise<void> => {
try {
const module = await moduleStore();
injectReducers(module.reducers);
setAlienModule(module);
} catch (err) {
throw new Error(`useDyno error: ${err}`);
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return alienModule;
}

export default {
createStore,
reloadStore,
injectReducers,
withStoreModule,
useAlienModule,
};
1 change: 1 addition & 0 deletions src/app/store/config/alienStore/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export { createStore } from './alienStore';
export { reloadStore } from './alienStore';
export { injectReducers } from './alienStore';
export { withStoreModule } from './alienStore';
export { useAlienModule } from './alienStore';

export { default } from './alienStore';

0 comments on commit bce2d50

Please sign in to comment.