From dd538096ab010af7109220d504d08a7f225f1f8d Mon Sep 17 00:00:00 2001 From: Vladimir Mosyaykin Date: Tue, 10 Sep 2024 22:18:17 +0200 Subject: [PATCH] improve defaultValue prop resolution --- src/hook/index.test.tsx | 45 ++++++++++++++++++++++++++++++++++++++++- src/hook/index.tsx | 8 ++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/hook/index.test.tsx b/src/hook/index.test.tsx index 9d4be7a..ecb4aea 100644 --- a/src/hook/index.test.tsx +++ b/src/hook/index.test.tsx @@ -13,6 +13,8 @@ import { useFetcher, type Navigation } from "@remix-run/react"; const submitMock = vi.fn(); const fetcherSubmitMock = vi.fn(); +const useActionDataMock = vi.hoisted(() => vi.fn()); + const useNavigationMock = vi.hoisted(() => vi.fn<() => Pick>(() => ({ state: "idle", @@ -22,7 +24,7 @@ const useNavigationMock = vi.hoisted(() => vi.mock("@remix-run/react", () => ({ useSubmit: () => submitMock, - useActionData: () => ({}), + useActionData: useActionDataMock, useFetcher: () => ({ submit: fetcherSubmitMock, data: {} }), useNavigation: useNavigationMock, })); @@ -257,6 +259,47 @@ describe("useRemixForm", () => { expect(result.current.formState.isSubmitting).toBe(false); }); + + it("should return defaultValue from the register function", async () => { + const { result, rerender } = renderHook(() => + useRemixForm({ + resolver: () => ({ + values: { name: "", address: { street: "" } }, + errors: {}, + }), + defaultValues: { + name: "Default name", + address: { + street: "Default street", + }, + }, + }), + ); + + let nameFieldProps = result.current.register("name"); + let streetFieldProps = result.current.register("address.street"); + + expect(nameFieldProps.defaultValue).toBe("Default name"); + expect(streetFieldProps.defaultValue).toBe("Default street"); + + useActionDataMock.mockReturnValue({ + defaultValues: { + name: "Updated name", + address: { + street: "Updated street", + }, + }, + errors: { name: "Enter another name" }, + }); + + rerender(); + + nameFieldProps = result.current.register("name"); + streetFieldProps = result.current.register("address.street"); + + expect(nameFieldProps.defaultValue).toBe("Updated name"); + expect(streetFieldProps.defaultValue).toBe("Updated street"); + }); }); afterEach(cleanup); diff --git a/src/hook/index.tsx b/src/hook/index.tsx index 9f6a65f..14136a3 100644 --- a/src/hook/index.tsx +++ b/src/hook/index.tsx @@ -20,6 +20,7 @@ import { useFormContext, useForm, FormProvider, + get, type DefaultValues, type FieldValues, type FormState, @@ -182,10 +183,13 @@ export const useRemixForm = ({ ) => ({ ...methods.register(name, options), ...(!options?.disableProgressiveEnhancement && { - defaultValue: data?.defaultValues?.[name] ?? "", + defaultValue: + get(data?.defaultValues, name) ?? + get(methods.formState.defaultValues, name) ?? + "", }), }), - [methods.register, data?.defaultValues], + [methods.register, data?.defaultValues, methods.formState], ); const handleSubmit = useMemo(