diff --git a/src/useField.test.js b/src/useField.test.js index 23cab6a..73df513 100644 --- a/src/useField.test.js +++ b/src/useField.test.js @@ -599,6 +599,38 @@ describe("useField", () => { expect(getByTestId("array").value).toBe("Apple"); }); + it("should return current form values on first render for newly added array fields", () => { + const renderSpy = jest.fn(); + const MyField = () => { + const { input, meta } = useField("items[0].name"); + renderSpy(input.value, meta.initial, meta.dirty); + return ; + }; + const { getByTestId } = render( +
+ )} + , + ); + + fireEvent.click(getByTestId("add")); + + expect(renderSpy.mock.calls[0]).toEqual(["Apple", undefined, true]); + expect(getByTestId("array").value).toBe("Apple"); + }); + it("should default undefined value to [] for select multiple with type prop (fix react-final-form-arrays #185)", () => { const renderSpy = jest.fn(); const MySelectField = () => { diff --git a/src/useField.ts b/src/useField.ts index db7b27a..eaea9c8 100644 --- a/src/useField.ts +++ b/src/useField.ts @@ -116,13 +116,42 @@ function useField< const formState = form.getState(); // Use getIn to support nested field paths like "user.name" or "items[0].id" const formInitialValue = formState.initialValues ? getIn(formState.initialValues, name) : undefined; - + + const formValue = formState.values + ? getIn(formState.values, name) + : undefined; + // Use Form initialValues if available, otherwise use field initialValue let initialStateValue = formInitialValue !== undefined ? formInitialValue : initialValue; - - if ((component === "select" || type === "select") && multiple && initialStateValue === undefined) { - initialStateValue = []; + + let value = + formInitialValue !== undefined + ? formValue + : formValue !== undefined + ? formValue + : initialStateValue; + + if ((component === "select" || type === "select") && multiple) { + if (value === undefined && initialStateValue === undefined) { + const emptyValue: any[] = []; + value = emptyValue; + initialStateValue = emptyValue; + } else { + if (value === undefined) { + value = + Array.isArray(initialStateValue) && initialStateValue.length === 0 + ? initialStateValue + : []; + } + + if (initialStateValue === undefined) { + initialStateValue = + Array.isArray(value) && value.length === 0 ? value : []; + } + } } + const isEqual = configRef.current.isEqual || ((a: any, b: any) => a === b); + const pristine = isEqual(value, initialStateValue); return { active: false, @@ -133,7 +162,7 @@ function useField< form.change(name as keyof FormValues, value); }, data: data || {}, - dirty: false, + dirty: !pristine, dirtySinceLastSubmit: false, error: undefined, focus: () => { @@ -145,7 +174,7 @@ function useField< modified: false, modifiedSinceLastSubmit: false, name, - pristine: true, + pristine, submitError: undefined, submitFailed: false, submitSucceeded: false, @@ -153,7 +182,7 @@ function useField< touched: false, valid: true, validating: false, - value: initialStateValue, + value, visited: false, }; });