Skip to content

Instantly share code, notes, and snippets.

Created May 1, 2017 22:20
Show Gist options
  • Save Aryk/5f69961736f4a546104587196d3ceab5 to your computer and use it in GitHub Desktop.
Save Aryk/5f69961736f4a546104587196d3ceab5 to your computer and use it in GitHub Desktop.
formHelper for react-redux-form
import { Reducer } from 'redux';
import { combineForms, FormState, FieldState } from 'react-redux-form';
export interface IFormHelper<Model> {
modelPath: string;
attributePath: (fieldName: keyof Model) => string;
modelAttributePath: (fieldName: keyof Model) => string;
dataSelector: (store: any) => Model;
fieldMetaDataSelector: (store: any) => (field: keyof Model) => FieldState;
formMetaDataSelector: (store: any) => FormState;
formEntry: (initialStateOrReducer: Partial<Model> | Reducer<any>) => object;
* We namespace everything form related under the 'form' reducer key, including the form states. The forms should not
* be where the model state is stored since forms are transient and can be cleared off and temporarily changed.
const reducerKeyName = 'form';
const formMetaDataKey = 'fieldMeta';
* Creates nested forms for react-redux-form. The idea here is to have a nested heirarchy as such:
* //=> 'My Favorite Video'
* //=> <field>
* //=> true
* //=> false
* Please read: for more information about
* the <field> structure.
* The default heirarchy would name "fieldMeta" as "forms", which is kind of confusing since the "forms" namespace
* does not actually include the field value, only metadata about the form.
const formsReducerEntry = (forms: object) => ({
[reducerKeyName]: combineForms(forms, reducerKeyName, {key: formMetaDataKey}),
const formHelper = <Model>(formName: string): IFormHelper<Model> => {
const modelPath = [reducerKeyName, formName].join('.'); // ie form.user
// The signifance of this is that it allows us to check again the FieldNameType for matches.
const attributePath = fieldName => '.'.concat(fieldName); // ie .firstName
return {
modelAttributePath: fieldName => modelPath.concat(attributePath(fieldName)), // ie form.user.firstName
dataSelector: mainState => mainState[reducerKeyName][formName],
fieldMetaDataSelector: mainState => field => mainState[reducerKeyName][formMetaDataKey][formName][field],
formMetaDataSelector: mainState => mainState[reducerKeyName][formMetaDataKey][formName].$form,
* Creates the entry to be put into the reducer where the key is the store key and value is the reducer.
formEntry: initialStateOrReducer => ({[formName]: initialStateOrReducer}),
export { formHelper, formsReducerEntry };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment