Skip to content

Commit 82d1542

Browse files
committed
fix(manager): fix rendering issues by rerendering forms on mount
1 parent edba16c commit 82d1542

File tree

5 files changed

+49
-16
lines changed

5 files changed

+49
-16
lines changed

packages/form-state-manager/src/files/use-field.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ const useField = ({
6666
beforeSubmit,
6767
afterSubmit,
6868
allowNull,
69-
silent,
7069
...props
7170
}: UseField): UseFieldData => {
7271
const { registerField, unregisterField, change, getFieldValue, blur, focus, formOptions, ...rest } = useContext(FormManagerContext);
@@ -85,7 +84,7 @@ const useField = ({
8584
defaultValue: dataType ? convertValue(defaultValue, dataType) : defaultValue,
8685
beforeSubmit,
8786
afterSubmit,
88-
silent
87+
silent: true
8988
});
9089

9190
return internalId;
@@ -121,8 +120,12 @@ const useField = ({
121120
};
122121

123122
useEffect(
124-
() => () => {
125-
unregisterField({ name, clearOnUnmount, internalId: id, value: finalClearedValue });
123+
() => {
124+
formOptions().afterSilentRegistration({ name, internalId: id });
125+
126+
return () => {
127+
unregisterField({ name, clearOnUnmount, internalId: id, value: finalClearedValue });
128+
};
126129
},
127130
[] // eslint-disable-line react-hooks/exhaustive-deps
128131
);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import useFieldArray from '../../files/use-field-array';
66
import FormStateManager from '../../files/form-state-manager';
77

88
const DummyInput = (props) => {
9-
const { input, meta } = useField({ ...props, silent: true });
9+
const { input, meta } = useField({ ...props });
1010
return <input {...input} />;
1111
};
1212

1313
const CompositeDummyInput = ({ name, ...props }) => {
14-
const firstField = useField({ ...props, name: `${name}.first-field`, silent: true });
15-
const secondField = useField({ ...props, name: `${name}.second-field`, silent: true });
14+
const firstField = useField({ ...props, name: `${name}.first-field` });
15+
const secondField = useField({ ...props, name: `${name}.second-field` });
1616
return (
1717
<Fragment>
1818
<input {...firstField.input} />

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ describe('useField', () => {
5858
name: 'spy',
5959
initialValue: 'foo',
6060
render: expect.any(Function),
61-
internalId: expect.any(Number)
61+
internalId: expect.any(Number),
62+
silent: true
6263
};
6364
const unregisterArguments = {
6465
name: 'spy',

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export type IsValidationPaused = () => boolean;
4444
export type PauseValidation = () => void;
4545
export type ResumeValidation = () => void;
4646
export type SetConfig = (attribute: keyof CreateManagerApiConfig, value: any) => void;
47+
export type AfterSilentRegistration = (field: Omit<FieldConfig, 'render'>) => void;
4748

4849
export interface AsyncWatcherRecord {
4950
[key: number]: Promise<unknown>;
@@ -110,7 +111,8 @@ export type ManagerApiFunctions =
110111
| 'isValidationPaused'
111112
| 'pauseValidation'
112113
| 'resumeValidation'
113-
| 'setConfig';
114+
| 'setConfig'
115+
| 'afterSilentRegistration';
114116

115117
export interface ManagerState {
116118
values: AnyObject;
@@ -142,6 +144,7 @@ export interface ManagerState {
142144
pauseValidation: PauseValidation;
143145
resumeValidation: ResumeValidation;
144146
setConfig: SetConfig;
147+
afterSilentRegistration: AfterSilentRegistration;
145148
registeredFields: Array<string>;
146149
fieldListeners: FieldListeners;
147150
active: string | undefined;

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ const createManagerApi: CreateManagerApi = ({
228228
pauseValidation,
229229
resumeValidation,
230230
setConfig,
231+
afterSilentRegistration,
231232
destroyOnUnregister,
232233
...initialFormState(initialValues)
233234
};
@@ -238,6 +239,8 @@ const createManagerApi: CreateManagerApi = ({
238239
let runFormValidation = false;
239240
let revalidatedFields: Array<string> = [];
240241
let registeringField: string | number | undefined;
242+
let isSilent = false;
243+
let silentRender: string[] = [];
241244

242245
const asyncWatcherApi = asyncWatcher(updateValidating, updateSubmitting);
243246

@@ -449,7 +452,9 @@ const createManagerApi: CreateManagerApi = ({
449452
return (subscribeTo: Array<string> = []) => {
450453
const changedAttributes = [...findDifference(snapshot, state), ...subscribeTo];
451454

452-
if (changedAttributes.length > 0) {
455+
if (isSilent) {
456+
changedAttributes.forEach((attr) => addIfUnique(silentRender, attr));
457+
} else if (changedAttributes.length > 0) {
453458
rerender(changedAttributes);
454459
}
455460
};
@@ -549,9 +554,10 @@ const createManagerApi: CreateManagerApi = ({
549554
}
550555

551556
function registerField(field: FieldConfig): void {
557+
isSilent = !!field.silent;
552558
registeringField = field.internalId || field.name;
553559
batch(() => {
554-
const render = !field.silent && prepareRerender();
560+
const render = prepareRerender();
555561
addIfUnique(state.registeredFields, field.name);
556562

557563
if (
@@ -590,17 +596,37 @@ const createManagerApi: CreateManagerApi = ({
590596
state.fieldListeners[field.name].state.meta.pristine = false;
591597
}
592598

593-
revalidateFields([field.name, ...(state.fieldListeners[field.name]?.validateFields || state.registeredFields.filter((n) => n !== field.name))]);
594-
595-
if (config.validate) {
596-
validateForm(config.validate);
599+
if (!field.silent) {
600+
revalidateFields([
601+
field.name,
602+
...(state.fieldListeners[field.name]?.validateFields || state.registeredFields.filter((n) => n !== field.name))
603+
]);
604+
if (config.validate) {
605+
validateForm(config.validate);
606+
}
597607
}
598608

599-
!field.silent && render && render();
609+
render();
600610
});
611+
isSilent = false;
601612
registeringField = undefined;
602613
}
603614

615+
function afterSilentRegistration(field: Omit<FieldConfig, 'render'>) {
616+
revalidateFields([field.name, ...(state.fieldListeners[field.name]?.validateFields || state.registeredFields.filter((n) => n !== field.name))]);
617+
618+
if (config.validate) {
619+
validateForm(config.validate);
620+
}
621+
622+
if (silentRender.length > 0) {
623+
registeringField = field.internalId || field.name;
624+
rerender(silentRender);
625+
silentRender = [];
626+
registeringField = undefined;
627+
}
628+
}
629+
604630
function unregisterField(field: Omit<FieldConfig, 'render'>): void {
605631
batch(() => {
606632
const render = prepareRerender();

0 commit comments

Comments
 (0)