From 519a0939d2bd9c208b1bebc49e3e2faadfc3a30f Mon Sep 17 00:00:00 2001 From: Jona Dimovska Date: Thu, 18 Jul 2019 20:48:15 +0200 Subject: [PATCH] Fixed FieldArray re-render on every change when subscription is empty object --- src/FieldArray.test.js | 62 +++++++++++++++++++++++++++++++++++++++--- src/testUtils.js | 5 ++++ src/useFieldArray.js | 2 +- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/FieldArray.test.js b/src/FieldArray.test.js index 77646b9..6e6b382 100644 --- a/src/FieldArray.test.js +++ b/src/FieldArray.test.js @@ -2,7 +2,7 @@ import React from 'react' import { render, fireEvent, cleanup } from '@testing-library/react' import 'jest-dom/extend-expect' import arrayMutators from 'final-form-arrays' -import { ErrorBoundary, Toggle } from './testUtils' +import { ErrorBoundary, Toggle, wrapWith } from './testUtils' import { Form, Field } from 'react-final-form' import { FieldArray, version } from '.' @@ -129,7 +129,7 @@ describe('FieldArray', () => { const renderArray = jest.fn(() =>
) class Container extends React.Component { state = { name: 'dogs' } - + render() { return (
@@ -149,10 +149,10 @@ describe('FieldArray', () => { expect(renderArray).toHaveBeenCalled() expect(renderArray).toHaveBeenCalledTimes(1) expect(renderArray.mock.calls[0][0].value).toBeUndefined() - + const button = TestUtils.findRenderedDOMComponentWithTag(dom, 'button') TestUtils.Simulate.click(button) - + expect(renderArray).toHaveBeenCalledTimes(2) expect(renderArray.mock.calls[1][0].value).toBeUndefined() }) @@ -445,6 +445,60 @@ describe('FieldArray', () => { expect(queryByTestId('names[1]')).not.toBe(null) }) + it('should not re-render Field when subscription is empty object', () => { + const nameFieldRender = jest.fn() + const surnameFieldRender = jest.fn() + + const { getByTestId } = render( + + {({ handleSubmit }) => ( + + + {({ fields }) => + fields.map(field => { + return ( +
+ + {wrapWith(nameFieldRender, ({ input }) => ( + + ))} + + + {wrapWith(surnameFieldRender, ({ input }) => ( + + ))} + +
+ ) + }) + } +
+
+ )} + + ) + + fireEvent.change(getByTestId('names[0].name'), { + target: { value: 'Sue' } + }) + expect(getByTestId('names[0].name').value).toBe('Sue') + + fireEvent.change(getByTestId('names[0].name'), { + target: { value: 'Paul' } + }) + expect(getByTestId('names[0].name').value).toBe('Paul') + + expect(nameFieldRender).toHaveBeenCalledTimes(3) + expect(surnameFieldRender).toHaveBeenCalledTimes(1) + }) + it('should allow Fields to be rendered for complex objects', () => { const onSubmit = jest.fn() const { getByTestId, getByText, queryByTestId } = render( diff --git a/src/testUtils.js b/src/testUtils.js index 49fd875..dae4c42 100644 --- a/src/testUtils.js +++ b/src/testUtils.js @@ -1,5 +1,10 @@ import React from 'react' +export const wrapWith = (mock, fn) => (...args) => { + mock(...args) + return fn(...args) +} + /** A simple container component that allows boolean to be toggled with a button */ export function Toggle({ children }) { const [on, setOn] = React.useState(false) diff --git a/src/useFieldArray.js b/src/useFieldArray.js index a8c9bb8..84863bb 100644 --- a/src/useFieldArray.js +++ b/src/useFieldArray.js @@ -57,7 +57,7 @@ const useFieldArray = ( input, ...fieldState } = useField(name, { - subscription: { ...subscription, value: true, length: true }, + subscription: { ...subscription, length: true }, isEqual, validate, format: v => v