davidkpiano / react-redux-form

Create forms easily in React with Redux.
https://davidkpiano.github.io/react-redux-form
MIT License
2.06k stars 252 forks source link

Made the usage of immutable strategy in createForms #1188

Closed mjangir closed 6 years ago

mjangir commented 6 years ago

I don't know why nobody faced this problem from the beginning but I found it today in createForms.

The Problem

While passing entire reducer function whose initial state is an immutable Map, this initial state is not being converted into plain JS object because the strategy was not used there but if we provide the immutable or non-immutable structure as formValue, they are perfectly being converted into plain JS object.

Steps to Reproduce

import { fromJS } from 'immutable';
import { createForms } from 'react-redux-form/immutable';

// Its a multistep form
const initialState = fromJS({
  basicDetails: {
    firstName: ''
  },
  corpDetails: {
    companyName: ''
  }
});
const userReducer = function(state = initialState, action) {
  return state;
}
const reducers = combineReducers({
  foo: fooReducer,
  ...createForms({
    user: userReducer // Its initial state is not converted to plain JS,
    user: userReducer(undefined, {type: null}) // this is converted to plain JS
  })
});

Both of the scenarios produce different forms object in global redux state.

What is fixed in this PR

When I debugged, found that in immutable.js, the strategy is passed to createFormCombiner but not being used when the formValue is a reducer function instead of imm/non-imm object. So modified that function a little bit and used toJS at both places:

formKeys.forEach((formKey) => {
      const formValue = forms[formKey];
      const subModel = getSubModelString(model, formKey);

      if (typeof formValue === 'function') {
        let initialState;
        try {
          initialState = formValue(undefined, NULL_ACTION);
        } catch (error) {
          initialState = null;
        }

        modelReducers[formKey] = strategy.modeled(formValue, subModel);
        initialFormState[formKey] = strategy.toJS(initialState);
      } else {
        modelReducers[formKey] = strategy.modelReducer(subModel, formValue);
        initialFormState[formKey] = strategy.toJS(formValue);
      }
    });
pratik916 commented 6 years ago

@mjangir Awesome workout