Skip to content

Commit

Permalink
Fixed FieldArray re-render on every change when subscription is empty…
Browse files Browse the repository at this point in the history
… object (#100)
  • Loading branch information
jdimovska authored and erikras committed Aug 4, 2019
1 parent 4fd4e5c commit 638d825
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
62 changes: 58 additions & 4 deletions src/FieldArray.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import { render, fireEvent, cleanup } from '@testing-library/react'
import '@testing-library/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 '.'

Expand Down Expand Up @@ -129,7 +129,7 @@ describe('FieldArray', () => {
const renderArray = jest.fn(() => <div />)
class Container extends React.Component {
state = { name: 'dogs' }
render() {
return (
<form>
Expand All @@ -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()
})
Expand Down Expand Up @@ -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(
<Form
onSubmit={onSubmitMock}
mutators={arrayMutators}
subscription={{}}
initialValues={{
names: [{ id: 1, name: 'John', surname: 'Doe' }]
}}
>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit} data-testid="form">
<FieldArray name="names" subscription={{}}>
{({ fields }) =>
fields.map(field => {
return (
<div key={`${field}.id`}>
<Field name={`${field}.name`}>
{wrapWith(nameFieldRender, ({ input }) => (
<input data-testid={`${field}.name`} {...input} />
))}
</Field>
<Field name={`${field}.surname`}>
{wrapWith(surnameFieldRender, ({ input }) => (
<input data-testid={`${field}.surname`} {...input} />
))}
</Field>
</div>
)
})
}
</FieldArray>
</form>
)}
</Form>
)

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(
Expand Down
5 changes: 5 additions & 0 deletions src/testUtils.js
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/useFieldArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 638d825

Please sign in to comment.