From e883b36605aca372c5e9015fc1dfed99722c2d70 Mon Sep 17 00:00:00 2001 From: Axel Tetzlaff Date: Mon, 13 May 2019 10:19:16 -0400 Subject: [PATCH] Fix Formstate.Nested in Formstate.List Using a nested property in a list would result in a "Cannot read property 'brand' of undefined" error when adding new items to the list. --- packages/react-form-state/CHANGELOG.md | 4 ++ .../src/components/Nested.tsx | 3 +- .../src/components/tests/List.test.tsx | 50 ++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/packages/react-form-state/CHANGELOG.md b/packages/react-form-state/CHANGELOG.md index 28b3ef281c..68731fe550 100644 --- a/packages/react-form-state/CHANGELOG.md +++ b/packages/react-form-state/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +### Fixed + +- `FormState.Nested` no longer breaks when used in a `FormState.List` and an item is added [#698](https://github.com/Shopify/quilt/pull/698) + ## [0.10.0] ### Changed diff --git a/packages/react-form-state/src/components/Nested.tsx b/packages/react-form-state/src/components/Nested.tsx index 9471f05421..d71c4ba0aa 100644 --- a/packages/react-form-state/src/components/Nested.tsx +++ b/packages/react-form-state/src/components/Nested.tsx @@ -23,7 +23,8 @@ export default class Nested extends React.PureComponent< const innerFields: FieldDescriptors = mapObject( value, (value, fieldPath) => { - const initialFieldValue = initialValue[fieldPath]; + const initialFieldValue = initialValue && initialValue[fieldPath]; + return { value, onBlur, diff --git a/packages/react-form-state/src/components/tests/List.test.tsx b/packages/react-form-state/src/components/tests/List.test.tsx index 0b322f94ad..2dfa6f02d7 100644 --- a/packages/react-form-state/src/components/tests/List.test.tsx +++ b/packages/react-form-state/src/components/tests/List.test.tsx @@ -6,7 +6,7 @@ import {trigger} from '@shopify/enzyme-utilities'; // eslint-disable-next-line shopify/strict-component-boundaries import {Input} from '../../tests/components'; import {lastCallArgs} from '../../tests/utilities'; -import FormState from '../..'; +import FormState, { arrayUtils } from '../..'; describe('', () => { it('passes form state into child function for each index of the given array', () => { @@ -339,4 +339,52 @@ describe('', () => { expect(updatedFields.title.value).toBe(newTitle); expect(updatedFields.department.value).toBe(newDepartment); }); + + it.only('does not raise an exceptions when list items are nested', () => { + const variants = [ + { + product: + { + title: faker.commerce.department(), + }, + }, + ]; + + const renderSpy = jest.fn(({title}) => { + return (); + }); + + let variantsRef; + mount( + + {({fields}) => { + variantsRef = fields.variants; + return (<> + + {nestedFields => ( + + {renderSpy} + + )} + + + );} + } + , + ); + + const newVariants = arrayUtils.push(variantsRef.value, + { + product: { + title: 'newProduct', + }, + } + ) + variantsRef.onChange(newVariants); + const calls = renderSpy.mock.calls; + const originalRenderCount = variants.length; + const rerenderedCount = originalRenderCount + 1; + expect(calls).toHaveLength(originalRenderCount + rerenderedCount); + + }); });