Update buildReducers
This commit is contained in:
parent
f0db8af726
commit
62f6adaf75
|
@ -22,10 +22,6 @@ const example = {
|
|||
})
|
||||
})
|
||||
}),
|
||||
test1: Types.reducer(Types.string),
|
||||
test2: Types.reducer(Types.arrayOf({
|
||||
foo5: Types.number,
|
||||
})),
|
||||
};
|
||||
|
||||
const test = buildReducers(example);
|
||||
|
|
|
@ -1,30 +1,92 @@
|
|||
//@flow
|
||||
import type { ShapeStructure } from './structure';
|
||||
//==============================
|
||||
// Flow imports
|
||||
//==============================
|
||||
import type { StructureType, PrimitiveType, ShapeStructure } from './structure';
|
||||
import type { PartialReducer, Selectors } from './reducers';
|
||||
|
||||
import { combineReducers } from 'redux';
|
||||
import { reduce, find } from 'lodash';
|
||||
import { createReducer } from './reducers';
|
||||
import { PROP_TYPES } from './structure';
|
||||
|
||||
export function buildReducers(structure: ShapeStructure) {
|
||||
|
||||
const tmp = combineReducers(reduce(structure, (memo, propValue, propName) => {
|
||||
const { structure } = propValue();
|
||||
type ProcessStructure = (
|
||||
memo: PartialReducer,
|
||||
propValue: StructureType|PrimitiveType,
|
||||
propName: string,
|
||||
) => PartialReducer;
|
||||
|
||||
const containsReducers = !!find(structure, v => v().type === PROP_TYPES._reducer);
|
||||
type BuildReducers = (name: string, structure: ShapeStructure, options: {
|
||||
baseSelector: Selectors,
|
||||
locationString: string,
|
||||
}) => PartialReducer;
|
||||
|
||||
const partial = {
|
||||
...memo,
|
||||
[propName]: containsReducers ? buildReducers(structure) : createReducer(propValue),
|
||||
export function buildReducers(name: string, structure: ShapeStructure, {
|
||||
baseSelector = state => state[name],
|
||||
locationString = name,
|
||||
}: {
|
||||
baseSelector: Selectors,
|
||||
locationString: string,
|
||||
}){
|
||||
|
||||
//Build up the reducers, actions, and selectors for this level. Due to recursion,
|
||||
//these objects will be assigned to a property in the parent object, or simply
|
||||
//returned to the call site for use in the rest of the application.
|
||||
const temp = reduce(structure, processStructure, {
|
||||
reducers: {},
|
||||
actionsObject: {},
|
||||
selectorsObject: {},
|
||||
});
|
||||
|
||||
//The Redux 'combineReducers' helper function is used here to save a little bit of boilerplate.
|
||||
//This helper, if you're not aware, ensures that the correct store properties are passed to the
|
||||
//reducers assigned to those properties.
|
||||
return { ...temp, reducers: combineReducers(temp.reducers) };
|
||||
|
||||
function processStructure<ProcessStructure>(memo, propValue, propName) {
|
||||
//Get the structure from the propValue. In the case of 'StructureType' properties, this
|
||||
//will be some form of shape (or primitives in the case of arrays). At this point we
|
||||
//are only interested in whether or not the structure contains reducers, as that
|
||||
//has an impact on how we proceed with regards to calls.
|
||||
const { structure: propStructure} = propValue();
|
||||
const containsReducers = !!find(propStructure, v => v().type === PROP_TYPES._reducer);
|
||||
|
||||
//Create the child reducer. Depending on whether or not the current structure level contains
|
||||
//child reducers, we will either recursively call buildReducers, or we will call the
|
||||
//createReducer function, which will create the correct reducer for the given structure
|
||||
//(which can be either object, array, or primitive).
|
||||
let childReducer = containsReducers ? buildReducers(propName, structure, {
|
||||
locationString: `${locationString}.${propName}`,
|
||||
baseSelector: state => baseSelector(state)[propName],
|
||||
}) : createReducer(propValue);
|
||||
|
||||
//As the object is built up, we want to assign the reducers/actions created
|
||||
//by the child to a location on the reducers/actions object which will match up
|
||||
//to their location. Selectors are created at this level, as the child does not
|
||||
//need to know where it is located within the grand scheme of things.
|
||||
return {
|
||||
reducers: {
|
||||
...memo.reducers,
|
||||
[propName]: childReducer.reducers,
|
||||
},
|
||||
actionsObject: {
|
||||
...memo.actionsObject,
|
||||
[propName]: childReducer.actionsObject,
|
||||
},
|
||||
selectorsObject: {
|
||||
...memo.selectorsObject,
|
||||
[propName]: state => baseSelector(state)[propName],
|
||||
},
|
||||
};
|
||||
|
||||
return partial;
|
||||
}, {}));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
//@flow
|
||||
//==============================
|
||||
// Flow imports
|
||||
//==============================
|
||||
import type { ObjectReducer, ObjectAction, ObjectSelector } from './reducers/objectReducer';
|
||||
|
||||
import {
|
||||
PROP_TYPES,
|
||||
} from './structure';
|
||||
|
@ -8,6 +13,15 @@ import { primitiveReducer } from './reducers/primitiveReducer';
|
|||
import { createObjectReducer } from './reducers/objectReducer';
|
||||
import { arrayReducer } from './reducers/arrayReducer';
|
||||
|
||||
export type Selectors = ObjectSelector;
|
||||
export type Actions = ObjectAction;
|
||||
export type Reducers = ObjectReducer;
|
||||
export type PartialReducer = {
|
||||
reducers: { [key: string]: Reducers},
|
||||
actionsObject: { [key: string]: Actions },
|
||||
selectorsObject?: { [key: string]: Selectors },
|
||||
};
|
||||
|
||||
function determineReducerType(reducerDescriptor) {
|
||||
const { structure } = reducerDescriptor();
|
||||
const { type } = structure();
|
||||
|
|
|
@ -31,6 +31,7 @@ export type ObjectReducerOptions = {
|
|||
behaviorsConfig: ObjectReducerBehaviorsConfig,
|
||||
locationString: string,
|
||||
};
|
||||
export type ObjectSelector = (state: Object) => Object;
|
||||
|
||||
//==============================
|
||||
// JS imports
|
||||
|
@ -61,9 +62,10 @@ export function createObjectReducer(reducerShape: StructureType, {
|
|||
behaviorsConfig = {},
|
||||
locationString
|
||||
}: ObjectReducerOptions) {
|
||||
const completeBehaviorsConfig = { ...DEFAULT_OBJECT_BEHAVIORS, ...behaviorsConfig };
|
||||
return {
|
||||
reducer: createReducer(reducerShape, createReducerBehaviors(behaviorsConfig, locationString)),
|
||||
actions: createActions(behaviorsConfig, locationString),
|
||||
reducers: createReducer(reducerShape, createReducerBehaviors(completeBehaviorsConfig, locationString)),
|
||||
actionsObject: createActions(completeBehaviorsConfig, locationString),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue