Repository: erikras/redux-form (js)

Issue:
Initial value for deeply nested forms when adding a field.
Is there any way I could add an initial value for nested form but only when I want to add it?
````js
export const fields = [
  "content",
  "children[].firstname",
  "children[].lastname"
];
````
And when I call `children.addField()` I want firstname to have an initial value. Looking into the code I see that addField receives 2 optional arguments and one of them is `value`, but if I try to use it

````js
children.addField({firstname: 'Tom', lastname: 'Whatever'})
````

it doesn't seem to work. I'm not sure I'm doing this right. 
I'm using v3.1.7.


Pull request:
Fix initialising a nested array value with an object in v4
This works off #411 and passes the `fields` to `initializeState` as required by v4.

This makes the test from #411 pass now, which I **think** is all thats required to fix #377. I also tested this fix in an app that I just upgraded to v4 and it fixes the behavior I was seeing.

Patch:
diff --git a/src/reducer.js b/src/reducer.js
index 7dbc0c57..a9f5be3a 100644
--- a/src/reducer.js
+++ b/src/reducer.js
@@ -20,7 +20,7 @@ const behaviors = {
     const array = read(path, state);
     const stateCopy = {...state};
     const arrayCopy = array ? [...array] : [];
-    const newValue = {value};
+    const newValue = value !== null && typeof value === 'object' ? initializeState(value, Object.keys(value)) : {value};
     if (index === undefined) {
       arrayCopy.push(newValue);
     } else {


Test patch:
diff --git a/src/__tests__/reducer.spec.js b/src/__tests__/reducer.spec.js
index 9b4bbacf..437e5802 100644
--- a/src/__tests__/reducer.spec.js
+++ b/src/__tests__/reducer.spec.js
@@ -78,7 +78,7 @@ describe('reducer', () => {
       });
   });
 
-  it('should add a deep array value with empty state', () => {
+  it('should add a deep array value with initial value', () => {
     const state = reducer({}, {
       ...addArrayValue('myField.myArray', 20, undefined),
       form: 'foo'
@@ -184,6 +184,293 @@ describe('reducer', () => {
       });
   });
 
+  it('should push a deep array value which is an object', () => {
+    const state = reducer({
+      testForm: {
+        myField: [
+          {
+            foo: {
+              initial: 'foo-1',
+              value: 'foo-1'
+            },
+            bar: {
+              initial: 'bar-1',
+              value: 'bar-1'
+            }
+          },
+          {
+            foo: {
+              initial: 'foo-2',
+              value: 'foo-2'
+            },
+            bar: {
+              initial: 'bar-2',
+              value: 'bar-2'
+            }
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      }
+    }, {
+      ...addArrayValue('myField', {foo: 'foo-3', bar: 'bar-3'}, undefined),
+      form: 'testForm'
+    });
+    expect(state.testForm)
+      .toEqual({
+        myField: [
+          {
+            foo: {
+              initial: 'foo-1',
+              value: 'foo-1'
+            },
+            bar: {
+              initial: 'bar-1',
+              value: 'bar-1'
+            }
+          },
+          {
+            foo: {
+              initial: 'foo-2',
+              value: 'foo-2'
+            },
+            bar: {
+              initial: 'bar-2',
+              value: 'bar-2'
+            }
+          },
+          {
+            foo: {
+              initial: 'foo-3',
+              value: 'foo-3'
+            },
+            bar: {
+              initial: 'bar-3',
+              value: 'bar-3'
+            }
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      });
+  });
+
+  it('should push a deep array value which is a nested object', () => {
+    const state = reducer({
+      testForm: {
+        myField: [
+          {
+            foo: {
+              initial: {a: 'foo-a1', b: 'foo-b1'},
+              value: {a: 'foo-a1', b: 'foo-b1'},
+            },
+            bar: {
+              initial: {a: 'bar-a1', b: 'bar-b1'},
+              value: {a: 'bar-a1', b: 'bar-b1'},
+            }
+          },
+          {
+            foo: {
+              initial: {a: 'foo-a2', b: 'foo-b2'},
+              value: {a: 'foo-a2', b: 'foo-b2'},
+            },
+            bar: {
+              initial: {a: 'bar-a2', b: 'bar-b2'},
+              value: {a: 'bar-a2', b: 'bar-b2'},
+            }
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      }
+    }, {
+      ...addArrayValue('myField', {foo: {a: 'foo-a3', b: 'foo-b3'}, bar: {a: 'bar-a3', b: 'bar-b3'}}, undefined),
+      form: 'testForm'
+    });
+    expect(state.testForm)
+      .toEqual({
+        myField: [
+          {
+            foo: {
+              initial: {a: 'foo-a1', b: 'foo-b1'},
+              value: {a: 'foo-a1', b: 'foo-b1'},
+            },
+            bar: {
+              initial: {a: 'bar-a1', b: 'bar-b1'},
+              value: {a: 'bar-a1', b: 'bar-b1'},
+            }
+          },
+          {
+            foo: {
+              initial: {a: 'foo-a2', b: 'foo-b2'},
+              value: {a: 'foo-a2', b: 'foo-b2'},
+            },
+            bar: {
+              initial: {a: 'bar-a2', b: 'bar-b2'},
+              value: {a: 'bar-a2', b: 'bar-b2'},
+            }
+          },
+          {
+            foo: {
+              initial: {a: 'foo-a3', b: 'foo-b3'},
+              value: {a: 'foo-a3', b: 'foo-b3'},
+            },
+            bar: {
+              initial: {a: 'bar-a3', b: 'bar-b3'},
+              value: {a: 'bar-a3', b: 'bar-b3'},
+            }
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      });
+  });
+
+  it('should push a subarray value which is an object', () => {
+    const state = reducer({
+      testForm: {
+        myField: [
+          {
+            myField2: [
+              {
+                foo: {
+                  initial: 'foo-1-1',
+                  value: 'foo-1-1'
+                },
+                bar: {
+                  initial: 'bar-1-1',
+                  value: 'bar-1-1'
+                }
+              },
+              {
+                foo: {
+                  initial: 'foo-1-2',
+                  value: 'foo-1-2'
+                },
+                bar: {
+                  initial: 'bar-1-2',
+                  value: 'bar-1-2'
+                }
+              },
+            ],
+          },
+          {
+            myField2: [
+              {
+                foo: {
+                  initial: 'foo-2-1',
+                  value: 'foo-2-1'
+                },
+                bar: {
+                  initial: 'bar-2-1',
+                  value: 'bar-2-1'
+                }
+              },
+              {
+                foo: {
+                  initial: 'foo-2-2',
+                  value: 'foo-2-2'
+                },
+                bar: {
+                  initial: 'bar-2-2',
+                  value: 'bar-2-2'
+                }
+              },
+            ],
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      }
+    }, {
+      ...addArrayValue('myField[1].myField2', {foo: 'foo-2-3', bar: 'bar-2-3'}, undefined),
+      form: 'testForm'
+    });
+    expect(state.testForm)
+      .toEqual({
+        myField: [
+          {
+            myField2: [
+              {
+                foo: {
+                  initial: 'foo-1-1',
+                  value: 'foo-1-1'
+                },
+                bar: {
+                  initial: 'bar-1-1',
+                  value: 'bar-1-1'
+                }
+              },
+              {
+                foo: {
+                  initial: 'foo-1-2',
+                  value: 'foo-1-2'
+                },
+                bar: {
+                  initial: 'bar-1-2',
+                  value: 'bar-1-2'
+                }
+              },
+            ],
+          },
+          {
+            myField2: [
+              {
+                foo: {
+                  initial: 'foo-2-1',
+                  value: 'foo-2-1'
+                },
+                bar: {
+                  initial: 'bar-2-1',
+                  value: 'bar-2-1'
+                }
+              },
+              {
+                foo: {
+                  initial: 'foo-2-2',
+                  value: 'foo-2-2'
+                },
+                bar: {
+                  initial: 'bar-2-2',
+                  value: 'bar-2-2'
+                }
+              },
+              {
+                foo: {
+                  initial: 'foo-2-3',
+                  value: 'foo-2-3'
+                },
+                bar: {
+                  initial: 'bar-2-3',
+                  value: 'bar-2-3'
+                }
+              },
+            ],
+          },
+        ],
+        _active: undefined,
+        _asyncValidating: false,
+        _error: undefined,
+        _submitting: false,
+        _submitFailed: false
+      });
+  });
+
   it('should set value on blur with empty state', () => {
     const state = reducer({}, {
       ...blur('myField', 'myValue'),