Skip to content

Commit c45ffa1

Browse files
authored
Merge pull request #774 from rvsia/multipleIsEqual
fix(manager): allow multiple isEqual for a field
2 parents 7c7d0f0 + cfeb18a commit c45ffa1

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

packages/form-state-manager/src/tests/files/use-field.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ describe('useField', () => {
451451

452452
expect(wrapper.find(SpyComponent).prop('meta')).toEqual(expect.objectContaining({ validating: false, valid: true }));
453453

454-
await act(() => {
454+
await act(async () => {
455455
input.simulate('change', { target: { value: 'foo' } });
456456
});
457457
/**

packages/form-state-manager/src/tests/utils/manager-api.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,42 @@ describe('managerApi', () => {
155155

156156
expect(isEqual).toHaveBeenCalledWith('cosi', 'initial');
157157
});
158+
159+
it('should compute value using isEqual - multiple functions - false result', () => {
160+
const managerApi = createManagerApi({ initialValues: { field1: 'initial' } });
161+
162+
const render = jest.fn();
163+
const isEqual = jest.fn().mockImplementation(() => true);
164+
const isEqual2 = jest.fn().mockImplementation(() => false);
165+
166+
managerApi().registerField({ name: 'field1', internalId: 1, render, isEqual });
167+
managerApi().registerField({ name: 'field1', internalId: 2, render, isEqual: isEqual2 });
168+
169+
managerApi().change('field1', 'cosi');
170+
171+
expect(isEqual).toHaveBeenCalledWith('cosi', 'initial');
172+
expect(isEqual2).toHaveBeenCalledWith('cosi', 'initial');
173+
174+
expect(managerApi().getFieldState('field1').pristine).toEqual(false);
175+
});
176+
177+
it('should compute value using isEqual - multiple functions - true result', () => {
178+
const managerApi = createManagerApi({ initialValues: { field1: 'initial' } });
179+
180+
const render = jest.fn();
181+
const isEqual = jest.fn().mockImplementation(() => true);
182+
const isEqual2 = jest.fn().mockImplementation(() => true);
183+
184+
managerApi().registerField({ name: 'field1', internalId: 1, render, isEqual });
185+
managerApi().registerField({ name: 'field1', internalId: 2, render, isEqual: isEqual2 });
186+
187+
managerApi().change('field1', 'cosi');
188+
189+
expect(isEqual).toHaveBeenCalledWith('cosi', 'initial');
190+
expect(isEqual2).toHaveBeenCalledWith('cosi', 'initial');
191+
192+
expect(managerApi().getFieldState('field1').pristine).toEqual(true);
193+
});
158194
});
159195

160196
it('should change different api instance separatelly', () => {

packages/form-state-manager/src/types/manager-api.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface ListenerField {
6565
afterSubmit?: AfterSubmit;
6666
beforeSubmit?: BeforeSubmit;
6767
validate?: Validator;
68+
isEqual?: IsEqual;
6869
}
6970

7071
export interface FieldListenerFields {
@@ -74,7 +75,6 @@ export interface FieldListenerFields {
7475
export interface FieldListener {
7576
count: number;
7677
state: FieldState;
77-
isEqual?: IsEqual;
7878
asyncWatcher: AsyncWatcherApi;
7979
fields: FieldListenerFields;
8080
validateFields?: Array<string>;

packages/form-state-manager/src/utils/manager-api.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import CreateManagerApi, {
2222
CreateManagerApiConfig
2323
} from '../types/manager-api';
2424
import AnyObject from '../types/any-object';
25-
import FieldConfig from '../types/field-config';
25+
import FieldConfig, { IsEqual } from '../types/field-config';
2626
import { Meta } from '../types/use-field';
2727
import { formLevelValidator, isPromise } from './validate';
2828
import { FormValidator, FormLevelError, Validator } from '../types/validate';
@@ -429,7 +429,15 @@ const createManagerApi: CreateManagerApi = ({
429429

430430
// TODO modify all affected field state variables
431431
batch(() => {
432-
const isEqualFn = state.fieldListeners[name]?.isEqual || defaultIsEqual;
432+
const allIsEqual: Array<IsEqual> = state.fieldListeners[name]
433+
? Object.values(state.fieldListeners[name].fields)
434+
.map(({ isEqual }) => isEqual as IsEqual, [])
435+
.filter(Boolean)
436+
: [];
437+
438+
const isEqualFn =
439+
allIsEqual.length > 0 ? (a: any, b: any) => allIsEqual.reduce((acc: boolean, curr: IsEqual) => acc && curr(a, b), true) : defaultIsEqual;
440+
433441
const pristine = isEqualFn(value, state.fieldListeners[name]?.state?.meta?.initial || get(state.initialValues, name));
434442

435443
setFieldState(name, (prevState) => ({
@@ -663,15 +671,15 @@ const createManagerApi: CreateManagerApi = ({
663671
: {}),
664672
count: (state.fieldListeners[subscriberConfig.name]?.count || 0) + 1,
665673
validateFields: subscriberConfig.validateFields,
666-
isEqual: subscriberConfig.isEqual,
667674
fields: {
668675
...state.fieldListeners[subscriberConfig.name]?.fields,
669676
[subscriberConfig.internalId || subscriberConfig.name]: {
670677
validate: subscriberConfig.validate,
671678
render: subscriberConfig.render,
672679
subscription: subscriberConfig.subscription,
673680
afterSubmit: subscriberConfig.afterSubmit,
674-
beforeSubmit: subscriberConfig.beforeSubmit
681+
beforeSubmit: subscriberConfig.beforeSubmit,
682+
isEqual: subscriberConfig.isEqual
675683
}
676684
}
677685
};

0 commit comments

Comments
 (0)