From b30af537a9a9081a961d0855e358f1137d26c0db Mon Sep 17 00:00:00 2001 From: Kyle Saxberg Date: Mon, 28 Jan 2019 10:02:23 -0800 Subject: [PATCH 1/5] go back to transformed classes --- .babelrc.js | 1 + package-lock.json | 25 ++++++++++++++++++++++++- package.json | 1 + src/factory.js | 44 ++++++++++++++++++++++---------------------- src/factoryMap.js | 32 ++++++++++++++++---------------- 5 files changed, 64 insertions(+), 39 deletions(-) diff --git a/.babelrc.js b/.babelrc.js index 4dd6e63..b348cb2 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -9,6 +9,7 @@ module.exports = { "@babel/flow" ], plugins: [ + "@babel/proposal-class-properties", "@babel/proposal-object-rest-spread", "transform-imports", "@babel/transform-modules-commonjs" diff --git a/package-lock.json b/package-lock.json index 18af2c6..8eb2558 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "redux-rags", - "version": "1.2.0-beta1", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -503,6 +503,19 @@ "@babel/types": "7.3.0" } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.0.tgz", + "integrity": "sha512-DUsQNS2CGLZZ7I3W3fvh0YpPDd6BuWJlDl+qmZZpABZHza2ErE3LxtEzLJFHFC1ZwtlAXvHhbFYbtM5o5B0WBw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.1.0", + "@babel/helper-member-expression-to-functions": "7.0.0", + "@babel/helper-optimise-call-expression": "7.0.0", + "@babel/helper-plugin-utils": "7.0.0", + "@babel/helper-replace-supers": "7.2.3" + } + }, "@babel/helper-define-map": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", @@ -741,6 +754,16 @@ "@babel/plugin-syntax-async-generators": "7.2.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz", + "integrity": "sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "7.3.0", + "@babel/helper-plugin-utils": "7.0.0" + } + }, "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", diff --git a/package.json b/package.json index 4413610..fde174d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.2.2", + "@babel/plugin-proposal-class-properties": "^7.3.0", "@babel/plugin-proposal-object-rest-spread": "^7.3.1", "@babel/plugin-transform-modules-commonjs": "^7.2.0", "@babel/preset-env": "^7.3.1", diff --git a/src/factory.js b/src/factory.js index 5110b37..8839601 100644 --- a/src/factory.js +++ b/src/factory.js @@ -86,15 +86,15 @@ const createFactory = (injectReducer: Function) => >(config: generatedCount += 1; const safeDataName = `${name}/${generatedCount}`; - const Getters = new function () { - const wrappedGetInitialState: () => BoilerState = createGetInitialState(getInitialState); - this.getInitialState = wrappedGetInitialState; + const wrappedGetInitialState: () => BoilerState = createGetInitialState(getInitialState); + class Getters { + getInitialState = wrappedGetInitialState; - this.get = getInStore || + get = getInStore || ((reduxStore: Object): BoilerState => reduxStore[prefix][safeDataName] || this.getInitialState()); - this.getData = (reduxStore: Object): $PropertyType, 'data'> => { + getData = (reduxStore: Object): $PropertyType, 'data'> => { const state = this.get(reduxStore); if (!state.hasOwnProperty('data')) { warning(`redux-rags: getData failed to find the property \'data\' on the object returned by Getters.get. @@ -103,7 +103,7 @@ const createFactory = (injectReducer: Function) => >(config: return state.data; }; - this.getMeta = (reduxStore: Object): $PropertyType, 'meta'> => { + getMeta = (reduxStore: Object): $PropertyType, 'meta'> => { const state = this.get(reduxStore); if (!state.hasOwnProperty('meta')) { warning(`redux-rags: getData failed to find the property \'meta\' on the object returned by Getters.get. @@ -112,11 +112,11 @@ const createFactory = (injectReducer: Function) => >(config: return state.meta; }; - this.getIsLoading = (reduxStore: Object) => { + getIsLoading = (reduxStore: Object) => { const meta = this.getMeta(reduxStore); return meta && meta.loading; }; - }; + } const BEGIN_LOADING = getLoadingType(name); const END_LOADING = getEndLoadingType(name); @@ -124,38 +124,38 @@ const createFactory = (injectReducer: Function) => >(config: const UPDATE_DATA = getUpdateType(name); const RESET = getResetType(name); - const Actions = new function(){ - this.beginLoading = () => ({ + class Actions { + beginLoading = () => ({ type: BEGIN_LOADING, payload: null, }); - this.endLoading = () => ({ + endLoading = () => ({ type: END_LOADING, payload: null, }); - this.reset = () => ({ + reset = () => ({ type: RESET, payload: null, }); - this.errors = (errors: Object | String) => ({ + errors = (errors: Object | String) => ({ type: ERRORS, payload: errors, }); - this.clearErrors = () => ({ + clearErrors = () => ({ type: ERRORS, payload: null, }); - this.updateData = (data: ?T) => ({ + updateData = (data: ?T) => ({ type: UPDATE_DATA, payload: data, }); - this.update = (...args: *) => async (dispatch, getState: () => Object) => { + update = (...args: *) => async (dispatch, getState: () => Object) => { if (!update || typeof update !== 'function') { return; } @@ -167,7 +167,7 @@ const createFactory = (injectReducer: Function) => >(config: } }; - this.load = (...args: G) => async ( + load = (...args: G) => async ( dispatch: Dispatch, getState: () => Object ): Promise => { @@ -191,7 +191,7 @@ const createFactory = (injectReducer: Function) => >(config: return null; } }; - }; + } type Interpret = ((...Iterable) => R) => R; type ExtractReturn = $Call; @@ -202,10 +202,10 @@ const createFactory = (injectReducer: Function) => >(config: | ExtractReturn | ExtractReturn | ExtractReturn; - const Subreducer = new function() { - this.partialReducer = partialReducer; + class Subreducer { + partialReducer = partialReducer; - this.subreduce = ( + subreduce = ( state?: BoilerState = Getters.getInitialState(), action?: GeneratedAction | * // Support other action types ) => { @@ -241,7 +241,7 @@ const createFactory = (injectReducer: Function) => >(config: return state; } }; - }; + } if (!getInStore) { injectReducer([prefix, safeDataName], Subreducer.subreduce); diff --git a/src/factoryMap.js b/src/factoryMap.js index 532ce84..0681580 100644 --- a/src/factoryMap.js +++ b/src/factoryMap.js @@ -41,33 +41,33 @@ const createFactoryMap = (injectReducer: Function) => { const safeDataName = `${name}/${generatedCount}`; const mapArgsToGenerated = {}; - const Getters = new function() { - const _getInitialStateForKey: () => BoilerState = createGetInitialState(getInitialState); + class Getters { + _getInitialStateForKey: () => BoilerState = createGetInitialState(getInitialState); - this.get = (reduxStore: Object): MapState => + get = (reduxStore: Object): MapState => reduxStore[prefix] && reduxStore[prefix][safeDataName]; - this.getWithArgs = (reduxStore, ...args) => { + getWithArgs = (reduxStore, ...args) => { const argsKey = convertArgsToString(...args); const state = this.get(reduxStore); if (!state || !state.hasOwnProperty(argsKey)) { - return _getInitialStateForKey(); + return this._getInitialStateForKey(); } return state[argsKey]; }; - this.getData = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).data; + getData = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).data; - this.getMeta = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).meta; + getMeta = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).meta; - this.getIsLoading = (reduxStore: Object, ...args) => { + getIsLoading = (reduxStore: Object, ...args) => { const meta = this.getMeta(reduxStore, ...args); return meta.loading; }; - }; + } - const Actions = new function() { - const _queryOrCreateBoilerplate = (...args) => { + class Actions { + _queryOrCreateBoilerplate = (...args) => { const stringHash = convertArgsToString(...args); if (!mapArgsToGenerated[stringHash]) { // Need to generate everything for this. Luckily we have a generator @@ -85,10 +85,10 @@ const createFactoryMap = (injectReducer: Function) => { }; // Links to argument-less actions generated by the factory. - const _forwardActionForSubreducer = (actionName: string, { forwardArgs = false }: * = {}) => ( + _forwardActionForSubreducer = (actionName: string, { forwardArgs = false }: * = {}) => ( ...args: Array ) => async dispatch => { - const actions = _queryOrCreateBoilerplate(...args).actions; + const actions = this._queryOrCreateBoilerplate(...args).actions; const action = actions[actionName]; if (forwardArgs) { return dispatch(action(...args)); // Assumed to be loading arguments. @@ -96,11 +96,11 @@ const createFactoryMap = (injectReducer: Function) => { return dispatch(action()); }; - this.load = _forwardActionForSubreducer('load', { forwardArgs: true }); + load = this._forwardActionForSubreducer('load', { forwardArgs: true }); - this.reset = _forwardActionForSubreducer('reset'); + reset = this._forwardActionForSubreducer('reset'); - this.clearErrors = _forwardActionForSubreducer('clearErrors'); + clearErrors = this._forwardActionForSubreducer('clearErrors'); } return { From 29d5fb04a65fe6a32b5bd9a43fef351f2dc6f88f Mon Sep 17 00:00:00 2001 From: Kyle Saxberg Date: Mon, 28 Jan 2019 10:12:39 -0800 Subject: [PATCH 2/5] fix flow errors --- package.json | 2 +- src/factory.js | 50 +++++++++++++++++++++++------------------------ src/factoryMap.js | 28 +++++++++++++------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index fde174d..208944a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-rags", - "version": "1.2.0", + "version": "1.2.1-beta", "description": "Redux Reducers, Actions, and Getters. Simplified!", "main": "build/index.js", "scripts": { diff --git a/src/factory.js b/src/factory.js index 8839601..4ad313f 100644 --- a/src/factory.js +++ b/src/factory.js @@ -88,14 +88,14 @@ const createFactory = (injectReducer: Function) => >(config: const safeDataName = `${name}/${generatedCount}`; const wrappedGetInitialState: () => BoilerState = createGetInitialState(getInitialState); class Getters { - getInitialState = wrappedGetInitialState; + static getInitialState = wrappedGetInitialState; - get = getInStore || + static get = getInStore || ((reduxStore: Object): BoilerState => - reduxStore[prefix][safeDataName] || this.getInitialState()); + reduxStore[prefix][safeDataName] || Getters.getInitialState()); - getData = (reduxStore: Object): $PropertyType, 'data'> => { - const state = this.get(reduxStore); + static getData = (reduxStore: Object): $PropertyType, 'data'> => { + const state = Getters.get(reduxStore); if (!state.hasOwnProperty('data')) { warning(`redux-rags: getData failed to find the property \'data\' on the object returned by Getters.get. This is likely caused by providing an incorrect 'getInStore' configuration option.`); @@ -103,8 +103,8 @@ const createFactory = (injectReducer: Function) => >(config: return state.data; }; - getMeta = (reduxStore: Object): $PropertyType, 'meta'> => { - const state = this.get(reduxStore); + static getMeta = (reduxStore: Object): $PropertyType, 'meta'> => { + const state = Getters.get(reduxStore); if (!state.hasOwnProperty('meta')) { warning(`redux-rags: getData failed to find the property \'meta\' on the object returned by Getters.get. This is likely caused by providing an incorrect 'getInStore' configuration option.`); @@ -112,8 +112,8 @@ const createFactory = (injectReducer: Function) => >(config: return state.meta; }; - getIsLoading = (reduxStore: Object) => { - const meta = this.getMeta(reduxStore); + static getIsLoading = (reduxStore: Object) => { + const meta = Getters.getMeta(reduxStore); return meta && meta.loading; }; } @@ -125,49 +125,49 @@ const createFactory = (injectReducer: Function) => >(config: const RESET = getResetType(name); class Actions { - beginLoading = () => ({ + static beginLoading = () => ({ type: BEGIN_LOADING, payload: null, }); - endLoading = () => ({ + static endLoading = () => ({ type: END_LOADING, payload: null, }); - reset = () => ({ + static reset = () => ({ type: RESET, payload: null, }); - errors = (errors: Object | String) => ({ + static errors = (errors: Object | String) => ({ type: ERRORS, payload: errors, }); - clearErrors = () => ({ + static clearErrors = () => ({ type: ERRORS, payload: null, }); - updateData = (data: ?T) => ({ + static updateData = (data: ?T) => ({ type: UPDATE_DATA, payload: data, }); - update = (...args: *) => async (dispatch, getState: () => Object) => { + static update = (...args: *) => async (dispatch, getState: () => Object) => { if (!update || typeof update !== 'function') { return; } try { const manipulated = await Promise.resolve(update(Getters.getData(getState()), ...args)); - dispatch(this.updateData(manipulated)); + dispatch(Actions.updateData(manipulated)); } catch (err) { - dispatch(this.errors(err)); + dispatch(Actions.errors(err)); } }; - load = (...args: G) => async ( + static load = (...args: G) => async ( dispatch: Dispatch, getState: () => Object ): Promise => { @@ -180,14 +180,14 @@ const createFactory = (injectReducer: Function) => >(config: return state.data; } } - dispatch(this.beginLoading()); + dispatch(Actions.beginLoading()); try { const data = await Promise.resolve(load(...args)); - dispatch(this.updateData(data)); + dispatch(Actions.updateData(data)); return data; } catch (err) { - dispatch(this.errors(err)); - dispatch(this.endLoading()); + dispatch(Actions.errors(err)); + dispatch(Actions.endLoading()); return null; } }; @@ -203,9 +203,9 @@ const createFactory = (injectReducer: Function) => >(config: | ExtractReturn | ExtractReturn; class Subreducer { - partialReducer = partialReducer; + static partialReducer = partialReducer; - subreduce = ( + static subreduce = ( state?: BoilerState = Getters.getInitialState(), action?: GeneratedAction | * // Support other action types ) => { diff --git a/src/factoryMap.js b/src/factoryMap.js index 0681580..5499ddc 100644 --- a/src/factoryMap.js +++ b/src/factoryMap.js @@ -42,32 +42,32 @@ const createFactoryMap = (injectReducer: Function) => { const safeDataName = `${name}/${generatedCount}`; const mapArgsToGenerated = {}; class Getters { - _getInitialStateForKey: () => BoilerState = createGetInitialState(getInitialState); + static _getInitialStateForKey: () => BoilerState = createGetInitialState(getInitialState); - get = (reduxStore: Object): MapState => + static get = (reduxStore: Object): MapState => reduxStore[prefix] && reduxStore[prefix][safeDataName]; - getWithArgs = (reduxStore, ...args) => { + static getWithArgs = (reduxStore, ...args) => { const argsKey = convertArgsToString(...args); - const state = this.get(reduxStore); + const state = Getters.get(reduxStore); if (!state || !state.hasOwnProperty(argsKey)) { return this._getInitialStateForKey(); } return state[argsKey]; }; - getData = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).data; + static getData = (reduxStore, ...args) => Getters.getWithArgs(reduxStore, ...args).data; - getMeta = (reduxStore, ...args) => this.getWithArgs(reduxStore, ...args).meta; + static getMeta = (reduxStore, ...args) => Getters.getWithArgs(reduxStore, ...args).meta; - getIsLoading = (reduxStore: Object, ...args) => { - const meta = this.getMeta(reduxStore, ...args); + static getIsLoading = (reduxStore: Object, ...args) => { + const meta = Getters.getMeta(reduxStore, ...args); return meta.loading; }; } class Actions { - _queryOrCreateBoilerplate = (...args) => { + static _queryOrCreateBoilerplate = (...args) => { const stringHash = convertArgsToString(...args); if (!mapArgsToGenerated[stringHash]) { // Need to generate everything for this. Luckily we have a generator @@ -85,10 +85,10 @@ const createFactoryMap = (injectReducer: Function) => { }; // Links to argument-less actions generated by the factory. - _forwardActionForSubreducer = (actionName: string, { forwardArgs = false }: * = {}) => ( + static _forwardActionForSubreducer = (actionName: string, { forwardArgs = false }: * = {}) => ( ...args: Array ) => async dispatch => { - const actions = this._queryOrCreateBoilerplate(...args).actions; + const actions = Actions._queryOrCreateBoilerplate(...args).actions; const action = actions[actionName]; if (forwardArgs) { return dispatch(action(...args)); // Assumed to be loading arguments. @@ -96,11 +96,11 @@ const createFactoryMap = (injectReducer: Function) => { return dispatch(action()); }; - load = this._forwardActionForSubreducer('load', { forwardArgs: true }); + static load = Actions._forwardActionForSubreducer('load', { forwardArgs: true }); - reset = this._forwardActionForSubreducer('reset'); + static reset = Actions._forwardActionForSubreducer('reset'); - clearErrors = this._forwardActionForSubreducer('clearErrors'); + static clearErrors = Actions._forwardActionForSubreducer('clearErrors'); } return { From 066ba0694c34530e616fc069a7d98dea5c38322a Mon Sep 17 00:00:00 2001 From: Kyle Saxberg Date: Mon, 28 Jan 2019 10:13:59 -0800 Subject: [PATCH 3/5] fix jest tests --- src/factory.js | 4 ++-- src/factoryMap.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/factory.js b/src/factory.js index 4ad313f..5b9eb07 100644 --- a/src/factory.js +++ b/src/factory.js @@ -235,8 +235,8 @@ const createFactory = (injectReducer: Function) => >(config: case RESET: return (Getters.getInitialState(): BoilerState); default: - if (typeof this.partialReducer === 'function') { - return {...state, ...(this.partialReducer(state, action) || {})}; + if (typeof Subreducer.partialReducer === 'function') { + return {...state, ...(Subreducer.partialReducer(state, action) || {})}; } return state; } diff --git a/src/factoryMap.js b/src/factoryMap.js index 5499ddc..f6d08a2 100644 --- a/src/factoryMap.js +++ b/src/factoryMap.js @@ -51,7 +51,7 @@ const createFactoryMap = (injectReducer: Function) => { const argsKey = convertArgsToString(...args); const state = Getters.get(reduxStore); if (!state || !state.hasOwnProperty(argsKey)) { - return this._getInitialStateForKey(); + return Getters._getInitialStateForKey(); } return state[argsKey]; }; From 527fb9a11fee7c3e0bcd2dcf2bac2938345a21b7 Mon Sep 17 00:00:00 2001 From: Kyle Saxberg Date: Mon, 28 Jan 2019 17:19:07 -0800 Subject: [PATCH 4/5] add new test, fix recursion issue! --- README.md | 2 +- package-lock.json | 8 +++++- package.json | 3 ++- src/combineAsyncReducers.js | 3 +-- src/factory.js | 12 +-------- src/factoryMap.js | 30 ++++++++++----------- test/integration.test.js | 52 +++++++++++++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 test/integration.test.js diff --git a/README.md b/README.md index b3f4b56..ed9d7f0 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ need to handle the addition of dynamic reducers! Here's what your Redux store creation will look like: ```js -import { combineReducers, createStore, applyMiddleware } from 'redux'; +import { compose, combineReducers, createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import { combineAsyncReducers, configureRags } from 'redux-rags'; diff --git a/package-lock.json b/package-lock.json index 8eb2558..b8b1ba0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "redux-rags", - "version": "1.2.0", + "version": "1.2.1-beta2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7276,6 +7276,12 @@ "symbol-observable": "1.2.0" } }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==", + "dev": true + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", diff --git a/package.json b/package.json index 208944a..4b28815 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-rags", - "version": "1.2.1-beta", + "version": "1.2.1-beta3", "description": "Redux Reducers, Actions, and Getters. Simplified!", "main": "build/index.js", "scripts": { @@ -50,6 +50,7 @@ "flow-bin": "^0.86.0", "jest": "^23.6.0", "redux": "^4.0.1", + "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.1" } } diff --git a/src/combineAsyncReducers.js b/src/combineAsyncReducers.js index 07a2931..98a8555 100644 --- a/src/combineAsyncReducers.js +++ b/src/combineAsyncReducers.js @@ -10,12 +10,11 @@ const recursivelyCombineAsyncReducers = function (combineReducers: Function, asy for (let prop of Object.getOwnPropertyNames(asyncReducers)) { const subreducer = asyncReducers[prop]; if (typeof subreducer === 'object') { - recursivelyCombineAsyncReducers(combineReducers, subreducer); + reducers[prop] = recursivelyCombineAsyncReducers(combineReducers, subreducer); } else { reducers[prop] = subreducer; } } - return combineReducers(reducers); }; diff --git a/src/factory.js b/src/factory.js index 5b9eb07..aa0b89b 100644 --- a/src/factory.js +++ b/src/factory.js @@ -24,8 +24,6 @@ type ConfigType = { update?: (data: ?T, *) => ?T | Promise, getInStore?: (store: Object) => BoilerState, getInitialState?: () => T, - // Options - loadOnlyOnce?: ?boolean, }; type ReturnType> = { @@ -78,7 +76,6 @@ const createFactory = (injectReducer: Function) => >(config: name = '', load, getInStore, - loadOnlyOnce, getInitialState, update, partialReducer, @@ -168,18 +165,11 @@ const createFactory = (injectReducer: Function) => >(config: }; static load = (...args: G) => async ( - dispatch: Dispatch, - getState: () => Object + dispatch: Dispatch ): Promise => { if (!load) { return null; } - if (loadOnlyOnce) { - const state = Getters.get(getState()); - if (state && state.meta.loaded) { - return state.data; - } - } dispatch(Actions.beginLoading()); try { const data = await Promise.resolve(load(...args)); diff --git a/src/factoryMap.js b/src/factoryMap.js index f6d08a2..09fea99 100644 --- a/src/factoryMap.js +++ b/src/factoryMap.js @@ -34,14 +34,14 @@ let generatedCount = 0; const convertArgsToString = (...args) => JSON.stringify(args); const createFactoryMap = (injectReducer: Function) => { - const factory = createFactory(injectReducer); - return >(config: ConfigType): ReturnType => { - const { name = '', load, getInitialState } = config; - generatedCount += 1; - - const safeDataName = `${name}/${generatedCount}`; - const mapArgsToGenerated = {}; - class Getters { + const factory = createFactory(injectReducer); + return >(config: ConfigType): ReturnType => { + const { name = '', load, getInitialState } = config; + generatedCount += 1; + + const safeDataName = `${name}/${generatedCount}`; + const mapArgsToGenerated = {}; + class Getters { static _getInitialStateForKey: () => BoilerState = createGetInitialState(getInitialState); static get = (reduxStore: Object): MapState => @@ -64,9 +64,9 @@ const createFactoryMap = (injectReducer: Function) => { const meta = Getters.getMeta(reduxStore, ...args); return meta.loading; }; - } + } - class Actions { + class Actions { static _queryOrCreateBoilerplate = (...args) => { const stringHash = convertArgsToString(...args); if (!mapArgsToGenerated[stringHash]) { @@ -101,14 +101,14 @@ const createFactoryMap = (injectReducer: Function) => { static reset = Actions._forwardActionForSubreducer('reset'); static clearErrors = Actions._forwardActionForSubreducer('clearErrors'); - } + } - return { - actions: Actions, - getters: Getters, - }; + return { + actions: Actions, + getters: Getters, }; }; +}; export default createFactoryMap; diff --git a/test/integration.test.js b/test/integration.test.js new file mode 100644 index 0000000..7401373 --- /dev/null +++ b/test/integration.test.js @@ -0,0 +1,52 @@ +// @flow + +import { compose, combineReducers, createStore, applyMiddleware } from 'redux'; +import thunk from 'redux-thunk'; + +import { combineAsyncReducers, configureRags, ragFactory, ragFactoryMap } from '../src/index'; + + +describe('integration test', () => { + // Initializing the redux store. + const createRootReducer = (dynamicReducers: Object = {}) => { + dynamicReducers = combineAsyncReducers(combineReducers, dynamicReducers); + + return combineReducers(Object.assign({}, dynamicReducers, { + // ... list your reducers below + })); + }; + + const middleware = applyMiddleware(thunk); + const store = createStore(createRootReducer(), compose(middleware)); + configureRags(store, createRootReducer); + + + it('initializes store properly', () => { + expect(store).toBeTruthy(); + }); + + it('adds a reducer to state when calling factory load', async () => { + const { actions, getters } = ragFactory({ name: 'basic-test', load: () => true }); + const state = store.getState(); + expect(state['@@redux-rags']).toBeTruthy(); + expect(getters.getData(state)).toBe(null); + await store.dispatch(actions.load()); + const nextState = store.getState(); + expect(getters.getData(nextState)).toBe(true); + }); + + it('adds a reducer to state when calling factoryMap load', async () => { + let i = 1; + const { actions, getters } = ragFactoryMap({ getInitialState: () => 0, name: 'map-test', load: (negative) => negative ? -1 * i++ : i++ }); + const state = store.getState(); + expect(getters.getData(state, true)).toBe(0); + expect(getters.getData(state, false)).toBe(0); + + await store.dispatch(actions.load(true)); + await store.dispatch(actions.load(false)); + const nextState = store.getState(); + expect(nextState['@@redux-rags/map']).toBeTruthy(); + expect(getters.getData(nextState, true)).toBe(-1); + expect(getters.getData(nextState, false)).toBe(2); + }); +}); From a7ff2f68f618182ec6062367d4d27988889eb6f3 Mon Sep 17 00:00:00 2001 From: Kyle Saxberg Date: Mon, 28 Jan 2019 17:26:42 -0800 Subject: [PATCH 5/5] dont remove loadOnlyOnce --- package.json | 2 +- src/factory.js | 12 +++++++++++- src/index.js | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4b28815..82d3949 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redux-rags", - "version": "1.2.1-beta3", + "version": "1.2.1", "description": "Redux Reducers, Actions, and Getters. Simplified!", "main": "build/index.js", "scripts": { diff --git a/src/factory.js b/src/factory.js index aa0b89b..3f6cd09 100644 --- a/src/factory.js +++ b/src/factory.js @@ -24,6 +24,8 @@ type ConfigType = { update?: (data: ?T, *) => ?T | Promise, getInStore?: (store: Object) => BoilerState, getInitialState?: () => T, + // Options + loadOnlyOnce?: ?boolean, }; type ReturnType> = { @@ -75,6 +77,7 @@ const createFactory = (injectReducer: Function) => >(config: const { name = '', load, + loadOnlyOnce, getInStore, getInitialState, update, @@ -165,11 +168,18 @@ const createFactory = (injectReducer: Function) => >(config: }; static load = (...args: G) => async ( - dispatch: Dispatch + dispatch: Dispatch, + getState: () => Object ): Promise => { if (!load) { return null; } + if (loadOnlyOnce) { + const state = Getters.get(getState()); + if (state && state.meta.loaded) { + return state.data; + } + } dispatch(Actions.beginLoading()); try { const data = await Promise.resolve(load(...args)); diff --git a/src/index.js b/src/index.js index 3a4028a..1040f55 100644 --- a/src/index.js +++ b/src/index.js @@ -12,7 +12,7 @@ function configureRags(store: *, createRootReducer: *) { injectReducer = makeReducerInjector(store, createRootReducer); ragFactory = createFactory(injectReducer); ragFactoryMap = createFactoryMap(injectReducer); -}; +} export { combineAsyncReducers,