Skip to content

Commit 8c4731f

Browse files
authored
Merge pull request #10657 from marmelab/fix-FilterLiveForm-RHF-7.55.0
Fix `<FilterLiveForm>` compatibility with react-hook-form 7.55.0
2 parents 1db1591 + bc86f24 commit 8c4731f

2 files changed

Lines changed: 42 additions & 11 deletions

File tree

packages/ra-core/src/form/FilterLiveForm.spec.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
PerInputValidation,
1010
} from './FilterLiveForm.stories';
1111
import React from 'react';
12+
import { WithFilterListSection } from '../../../ra-ui-materialui/src/list/filter/FilterLiveForm.stories';
1213

1314
describe('<FilterLiveForm />', () => {
1415
it('should allow to set a filter value', async () => {
@@ -138,6 +139,30 @@ describe('<FilterLiveForm />', () => {
138139
).toBeNull();
139140
});
140141

142+
it('should not reapply old filter values when they change externally', async () => {
143+
render(<WithFilterListSection />);
144+
// Click on Yes
145+
fireEvent.click(await screen.findByText('Yes'));
146+
await screen.findByText('"has_newsletter": true', { exact: false });
147+
await new Promise(resolve => setTimeout(resolve, 510));
148+
await screen.findByText('"has_newsletter": true', { exact: false });
149+
// Click on No
150+
fireEvent.click(await screen.findByText('No'));
151+
await screen.findByText('"has_newsletter": false', { exact: false });
152+
await new Promise(resolve => setTimeout(resolve, 510));
153+
await screen.findByText('"has_newsletter": false', { exact: false });
154+
// Click on Yes
155+
fireEvent.click(await screen.findByText('Yes'));
156+
await screen.findByText('"has_newsletter": true', { exact: false });
157+
await new Promise(resolve => setTimeout(resolve, 510));
158+
await screen.findByText('"has_newsletter": true', { exact: false });
159+
// Click on No
160+
fireEvent.click(await screen.findByText('No'));
161+
await screen.findByText('"has_newsletter": false', { exact: false });
162+
await new Promise(resolve => setTimeout(resolve, 510));
163+
await screen.findByText('"has_newsletter": false', { exact: false });
164+
});
165+
141166
describe('getFilterFormValues', () => {
142167
it('should correctly get the filter form values from the new filterValues', () => {
143168
const currentFormValues = {
@@ -154,6 +179,7 @@ describe('<FilterLiveForm />', () => {
154179
nestedUpdated: { nestedValue: 'jkl2' },
155180
nestedToSet: { nestedValue: 'mno2' },
156181
published_at: '2022-01-01T03:00:00.000Z',
182+
newIgnoredValue: 'pqr',
157183
};
158184

159185
expect(

packages/ra-core/src/form/FilterLiveForm.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import isEqual from 'lodash/isEqual';
33
import cloneDeep from 'lodash/cloneDeep';
44
import get from 'lodash/get';
5+
import mergeWith from 'lodash/mergeWith';
56
import set from 'lodash/set';
67
import { ReactNode, useEffect } from 'react';
78
import { FormProvider, useForm, UseFormProps } from 'react-hook-form';
@@ -110,10 +111,7 @@ export const FilterLiveForm = (props: FilterLiveFormProps) => {
110111
return;
111112
}
112113
formChangesPending.current = true;
113-
setFilters({
114-
...filterValues,
115-
...values,
116-
});
114+
setFilters(mergeObjNotArray(filterValues, values));
117115
};
118116
const debouncedOnSubmit = useDebouncedEvent(onSubmit, debounce || 0);
119117

@@ -172,6 +170,16 @@ export interface FilterLiveFormProps
172170
>;
173171
}
174172

173+
// Lodash merge customizer to merge objects but not arrays
174+
const mergeCustomizer = (objValue: any, srcValue: any) => {
175+
if (Array.isArray(srcValue)) {
176+
return srcValue;
177+
}
178+
};
179+
180+
const mergeObjNotArray = (a: any, b: any) =>
181+
mergeWith(cloneDeep(a), b, mergeCustomizer);
182+
175183
/**
176184
* Because we are using controlled inputs with react-hook-form, we must provide a default value
177185
* for each input when resetting the form. (see https://react-hook-form.com/docs/useform/reset).
@@ -183,13 +191,10 @@ export const getFilterFormValues = (
183191
formValues: Record<string, any>,
184192
filterValues: Record<string, any>
185193
) => {
186-
return Object.keys(formValues).reduce(
187-
(acc, key) => {
188-
acc[key] = getInputValue(formValues, key, filterValues);
189-
return acc;
190-
},
191-
cloneDeep(filterValues) ?? {}
192-
);
194+
return Object.keys(formValues).reduce((acc, key) => {
195+
acc[key] = getInputValue(formValues, key, filterValues);
196+
return acc;
197+
}, {});
193198
};
194199

195200
const getInputValue = (

0 commit comments

Comments
 (0)