From 53dbf555c38c4d73964616c70c825f475851d64a Mon Sep 17 00:00:00 2001 From: Darya Saenko Date: Sun, 3 Nov 2019 16:01:27 +0300 Subject: [PATCH 1/3] Create instance without key --- .gitignore | 1 + src/create-instance.js | 26 ++++++++++++++++++++++---- src/reload-state.js | 3 +-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index e5e0b69..e972317 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ lib/ node_modules/ *.swp package-lock.json +.idea/ diff --git a/src/create-instance.js b/src/create-instance.js index 29205d0..4bac834 100644 --- a/src/create-instance.js +++ b/src/create-instance.js @@ -1,4 +1,5 @@ import { createDynamicMiddlewares } from 'redux-dynamic-middlewares' +import { combineReducers } from 'redux'; import { configureStore } from './configure-store' import { reloadState } from './reload-state' @@ -15,16 +16,32 @@ const createInstance = ({ thunk = {}, reducer = emptyReducer, middleware = emptyMiddleware, + useKey = true, withDevTools, } = {}) => { const dynamicMiddlewares = createDynamicMiddlewares() + const reducerWrapper = (reducer && reducer.wrapper) ? reducer.wrapper : combineReducers + const reducerInitial = (reducer && reducer.wrapper) ? reducer.wrapper(reducer.reducers) : emptyReducer + + let reducers + + // TODO: add check for reducer - that absent duplicate + if (useKey) { + reducers = { + [key]: (state = initial, action) => reducer(state, action), + } + } else { + reducers = (reducer && reducer.reducers) ? { ...reducer.reducers } : (state = initial, action) => reducer(state, action) + } + + dynamicMiddlewares.addMiddleware(middleware) + const registry = { keys: { [key]: true, }, - reducers: { - [key]: (state = initial, action) => reducer(state, action), - }, + reducers, + reducerWrapper, thunks: { [key]: thunk, }, @@ -37,7 +54,8 @@ const createInstance = ({ name, withDevTools, key, - reducer: emptyReducer, + initial, + reducer: reducerInitial, dynamicMiddlewares: dynamicMiddlewares.enhancer, }) diff --git a/src/reload-state.js b/src/reload-state.js index 3bed302..494583b 100644 --- a/src/reload-state.js +++ b/src/reload-state.js @@ -1,8 +1,7 @@ -import { combineReducers } from 'redux' import thunkMiddleware from 'redux-thunk' const reloadState = (registry, store, dynamicMiddlewares) => { - store.replaceReducer(combineReducers(registry.reducers)) + store.replaceReducer(registry.reducerWrapper(registry.reducers)) dynamicMiddlewares.resetMiddlewares() const thunkObject = thunkMiddleware.withExtraArgument(registry.thunks) From ed4591a2318120d3c4f80da7e85547000de2e6df Mon Sep 17 00:00:00 2001 From: Darya Saenko Date: Sat, 9 Nov 2019 23:45:32 +0300 Subject: [PATCH 2/3] Make create instance flat --- package.json | 2 +- src/create-instance-flat.js | 66 +++++++++++++++++++++++++++++ src/create-instance.js | 28 +++---------- src/index-flat.test.js | 82 +++++++++++++++++++++++++++++++++++++ src/index.js | 2 + 5 files changed, 157 insertions(+), 23 deletions(-) create mode 100644 src/create-instance-flat.js create mode 100644 src/index-flat.test.js diff --git a/package.json b/package.json index 46eeb9f..923961f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-dynamic", - "version": "1.2.0", + "version": "1.3.0-beta", "description": "Allow add or remove redux modules dynamically", "main": "lib/index.js", "scripts": { diff --git a/src/create-instance-flat.js b/src/create-instance-flat.js new file mode 100644 index 0000000..62ddd94 --- /dev/null +++ b/src/create-instance-flat.js @@ -0,0 +1,66 @@ +import { createDynamicMiddlewares } from 'redux-dynamic-middlewares' +import { combineReducers } from 'redux'; + +import { configureStore } from './configure-store' +import { reloadState } from './reload-state' +import { createAttach } from './create-attach' +import { createDetach } from './create-detach' + +const emptyMiddleware = () => next => action => next(action) +const emptyReducer = (state = {}) => state + +const createInstanceFlat = ({ + name = 'redux-dynamic', + key = '__EMPTY__', + initial = {}, + thunk = {}, + reducer = emptyReducer, + middleware = emptyMiddleware, + withDevTools, +} = {}) => { + const dynamicMiddlewares = createDynamicMiddlewares() + const reducerWrapper = reducer.wrapper ? reducer.wrapper : combineReducers + const reducerInitial = reducer.wrapper ? reducer.wrapper(reducer.reducers) : emptyReducer + const reducers = reducer.reducers ? { ...reducer.reducers } : { [key]: (state = initial, action) => reducer(state, action) } + + dynamicMiddlewares.addMiddleware(middleware) + + const registry = { + keys: { + [key]: true, + }, + reducers, + reducerWrapper, + thunks: { + [key]: thunk, + }, + middlewares: { + [key]: middleware, + }, + } + + const store = configureStore({ + name, + withDevTools, + key, + initial, + reducer: reducerInitial, + dynamicMiddlewares: dynamicMiddlewares.enhancer, + }) + + reloadState(registry, store, dynamicMiddlewares) + + const getStore = () => store + const attach = createAttach(registry, store, dynamicMiddlewares) + const detach = createDetach(registry, store, dynamicMiddlewares) + + return { + getStore, + attach, + detach, + } +} + +export { + createInstanceFlat, +} diff --git a/src/create-instance.js b/src/create-instance.js index 4bac834..8bb13bd 100644 --- a/src/create-instance.js +++ b/src/create-instance.js @@ -1,5 +1,5 @@ +import { combineReducers } from 'redux' import { createDynamicMiddlewares } from 'redux-dynamic-middlewares' -import { combineReducers } from 'redux'; import { configureStore } from './configure-store' import { reloadState } from './reload-state' @@ -16,32 +16,17 @@ const createInstance = ({ thunk = {}, reducer = emptyReducer, middleware = emptyMiddleware, - useKey = true, withDevTools, } = {}) => { const dynamicMiddlewares = createDynamicMiddlewares() - const reducerWrapper = (reducer && reducer.wrapper) ? reducer.wrapper : combineReducers - const reducerInitial = (reducer && reducer.wrapper) ? reducer.wrapper(reducer.reducers) : emptyReducer - - let reducers - - // TODO: add check for reducer - that absent duplicate - if (useKey) { - reducers = { - [key]: (state = initial, action) => reducer(state, action), - } - } else { - reducers = (reducer && reducer.reducers) ? { ...reducer.reducers } : (state = initial, action) => reducer(state, action) - } - - dynamicMiddlewares.addMiddleware(middleware) - const registry = { keys: { [key]: true, }, - reducers, - reducerWrapper, + reducers: { + [key]: (state = initial, action) => reducer(state, action), + }, + reducerWrapper: combineReducers, thunks: { [key]: thunk, }, @@ -54,8 +39,7 @@ const createInstance = ({ name, withDevTools, key, - initial, - reducer: reducerInitial, + reducer: emptyReducer, dynamicMiddlewares: dynamicMiddlewares.enhancer, }) diff --git a/src/index-flat.test.js b/src/index-flat.test.js new file mode 100644 index 0000000..d5b8566 --- /dev/null +++ b/src/index-flat.test.js @@ -0,0 +1,82 @@ +/* eslint-disable no-console */ +import { createInstanceFlat } from './index' + +const reducer = (state = {}, action) => { + if (action.type === 'foo') return { ...state, foo: 'bar' } + return state +} + +const complexReducer = { + reducers: { + one: reducer, + }, +} + +test('flat - without params', () => { + console.error = jest.fn() + + const dynamicStore = createInstanceFlat() + + const store = dynamicStore.getStore() + expect(store.getState()).toEqual({ __EMPTY__: {} }) + + store.dispatch({ type: 'foo' }) + expect(console.error).not.toBeCalled() +}) + +test('flat - one module with simple reducer', () => { + console.error = jest.fn() + + const dynamicStore = createInstanceFlat({ key: 'key', reducer }) + + const store = dynamicStore.getStore() + expect(store.getState()).toEqual({ key: {} }) + + store.dispatch({ type: 'foo' }) + expect(console.error).not.toBeCalled() + expect(store.getState()).toEqual({ key: { foo: 'bar' } }) +}) + +test('flat - one module with complex reducer', () => { + console.error = jest.fn() + + const dynamicStore = createInstanceFlat({ key: 'key', reducer: complexReducer }) + + const store = dynamicStore.getStore() + expect(store.getState()).toEqual({ one: {} }) + + store.dispatch({ type: 'foo' }) + expect(console.error).not.toBeCalled() + expect(store.getState()).toEqual({ one: { foo: 'bar' } }) +}) + +test('flat - attach and detach module', () => { + console.error = jest.fn() + + const dynamicStore = createInstanceFlat({ key: 'key', reducer: complexReducer }) + dynamicStore.attach({ key: 'two', reducer }) + + const store = dynamicStore.getStore() + expect(store.getState()).toEqual({ one: {}, two: {} }) + + store.dispatch({ type: 'foo' }) + expect(console.error).not.toBeCalled() + expect(store.getState()).toEqual({ one: { foo: 'bar' }, two: { foo: 'bar' } }) + + dynamicStore.detach({ key: 'two' }) + expect(store.getState()).toEqual({ one: { foo: 'bar' } }) +}) + +test('flat - initials', () => { + const initial = { one: 'bar' } + const initial2 = { foo: 'bar' } + + const dynamicStore = createInstanceFlat({ key: 'key', initial, reducer: complexReducer }) + dynamicStore.attach({ key: 'two', initial: initial2 }) + + const store = dynamicStore.getStore() + expect(store.getState()).toEqual({ one: 'bar', two: { foo: 'bar' } }) + + dynamicStore.detach({ key: 'two' }) + expect(store.getState()).toEqual({ one: 'bar' }) +}) diff --git a/src/index.js b/src/index.js index 1690574..7a25f8d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,9 @@ import { createInstance } from './create-instance' +import { createInstanceFlat } from './create-instance-flat' import { prepareActions } from './prepare-actions' export { createInstance, + createInstanceFlat, prepareActions, } From 3170aaaa1dd6de27fe4d5c1ccbf3a2edd1df59da Mon Sep 17 00:00:00 2001 From: Denis Iogansen Date: Fri, 22 Nov 2019 19:39:06 +0300 Subject: [PATCH 3/3] release version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 923961f..92eb820 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-dynamic", - "version": "1.3.0-beta", + "version": "1.3.0", "description": "Allow add or remove redux modules dynamically", "main": "lib/index.js", "scripts": {