Skip to content

Commit 138dd5a

Browse files
author
Dinesh Agent
committed
Fix #1050: useField returns Form initialValues on first render
PROBLEM: In v7.0.0, useField returns undefined on first render even when Form initialValues are set. This breaks apps trying to upgrade from v6. ROOT CAUSE: useField's useState initializer calls getFieldState() before the field is registered. Since the field doesn't exist yet, it falls back to creating initial state, but only checks field-level initialValue config, NOT the Form's initialValues. SOLUTION: Check form.getState().initialValues[name] when creating fallback initial state. Form-level initialValues take precedence over field-level. TESTS: - ✅ useField returns Form initialValues on first render - ✅ Form initialValues override field initialValue - ✅ Field initialValue used when Form initialValues missing that field Fixes #1050
1 parent 36ee99a commit 138dd5a

2 files changed

Lines changed: 81 additions & 1 deletion

File tree

src/useField.test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,4 +508,76 @@ describe("useField", () => {
508508
expect(calls).toContain("test"); // At least one call with 'test'
509509
expect(calls[calls.length - 1]).toBe(null); // Last call is null
510510
});
511+
512+
it("should return Form initialValues on first render (fix #1050)", () => {
513+
const renderSpy = jest.fn();
514+
515+
const MyField = () => {
516+
const { input } = useField("username");
517+
renderSpy(input.value);
518+
return <input {...input} data-testid="username" />;
519+
};
520+
521+
const { getByTestId } = render(
522+
<Form onSubmit={onSubmitMock} initialValues={{ username: "erikras" }}>
523+
{() => (
524+
<form>
525+
<MyField />
526+
</form>
527+
)}
528+
</Form>,
529+
);
530+
531+
// Critical: on the FIRST render, value should be "erikras" not undefined
532+
expect(renderSpy.mock.calls[0][0]).toBe("erikras");
533+
expect(getByTestId("username").value).toBe("erikras");
534+
});
535+
536+
it("should prefer Form initialValues over field initialValue", () => {
537+
const renderSpy = jest.fn();
538+
539+
const MyField = () => {
540+
const { input } = useField("username", { initialValue: "fallback" });
541+
renderSpy(input.value);
542+
return <input {...input} data-testid="username" />;
543+
};
544+
545+
const { getByTestId } = render(
546+
<Form onSubmit={onSubmitMock} initialValues={{ username: "formLevel" }}>
547+
{() => (
548+
<form>
549+
<MyField />
550+
</form>
551+
)}
552+
</Form>,
553+
);
554+
555+
// Form-level initialValues should take precedence
556+
expect(renderSpy.mock.calls[0][0]).toBe("formLevel");
557+
expect(getByTestId("username").value).toBe("formLevel");
558+
});
559+
560+
it("should use field initialValue when Form initialValues doesnt have that field", () => {
561+
const renderSpy = jest.fn();
562+
563+
const MyField = () => {
564+
const { input } = useField("username", { initialValue: "fieldLevel" });
565+
renderSpy(input.value);
566+
return <input {...input} data-testid="username" />;
567+
};
568+
569+
const { getByTestId } = render(
570+
<Form onSubmit={onSubmitMock} initialValues={{ other: "value" }}>
571+
{() => (
572+
<form>
573+
<MyField />
574+
</form>
575+
)}
576+
</Form>,
577+
);
578+
579+
// Field-level initialValue should be used as fallback
580+
expect(renderSpy.mock.calls[0][0]).toBe("fieldLevel");
581+
expect(getByTestId("username").value).toBe("fieldLevel");
582+
});
511583
});

src/useField.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,16 @@ function useField<
114114
}
115115

116116
// If no existing state, create a proper initial state
117+
// FIX #1050: Check Form's initialValues[name] first, before field-level initialValue
118+
const formState = form.getState();
117119
let initialStateValue = initialValue;
118-
if (component === "select" && multiple && initialValue === undefined) {
120+
121+
// Check Form-level initialValues (set via <Form initialValues={...}>)
122+
if (formState.initialValues && name in formState.initialValues) {
123+
initialStateValue = (formState.initialValues as any)[name];
124+
}
125+
126+
if (component === "select" && multiple && initialStateValue === undefined) {
119127
initialStateValue = [];
120128
}
121129

0 commit comments

Comments
 (0)