remix-validated-form 4.1.4-beta.0 → 4.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/browser/ValidatedForm.js +31 -36
- package/browser/hooks.js +13 -16
- package/browser/internal/customState.d.ts +105 -0
- package/browser/internal/customState.js +46 -0
- package/browser/internal/getInputProps.js +4 -14
- package/browser/internal/hooks.d.ts +14 -15
- package/browser/internal/hooks.js +37 -39
- package/browser/internal/logic/elementUtils.d.ts +3 -0
- package/browser/internal/logic/elementUtils.js +3 -0
- package/browser/internal/logic/setInputValueInForm.js +9 -52
- package/browser/internal/setFieldValue.d.ts +0 -0
- package/browser/internal/setFieldValue.js +0 -0
- package/browser/internal/setFormValues.d.ts +0 -0
- package/browser/internal/setFormValues.js +0 -0
- package/browser/internal/state.d.ts +339 -238
- package/browser/internal/state.js +59 -72
- package/browser/internal/watch.d.ts +18 -0
- package/browser/internal/watch.js +122 -0
- package/browser/unreleased/formStateHooks.d.ts +39 -0
- package/browser/unreleased/formStateHooks.js +54 -0
- package/browser/userFacingFormContext.js +9 -23
- package/build/ValidatedForm.js +30 -35
- package/build/hooks.js +11 -14
- package/build/internal/getInputProps.js +4 -14
- package/build/internal/hooks.d.ts +14 -15
- package/build/internal/hooks.js +39 -41
- package/build/internal/logic/elementUtils.d.ts +3 -0
- package/build/internal/logic/elementUtils.js +9 -0
- package/build/internal/logic/setInputValueInForm.js +12 -55
- package/build/internal/setFormValues.d.ts +0 -0
- package/build/internal/setFormValues.js +0 -0
- package/build/internal/state/controlledFields.js +11 -2
- package/build/internal/state.d.ts +339 -238
- package/build/internal/state.js +61 -77
- package/build/internal/watch.d.ts +20 -0
- package/build/internal/watch.js +126 -0
- package/build/unreleased/formStateHooks.d.ts +39 -0
- package/build/unreleased/formStateHooks.js +59 -0
- package/build/userFacingFormContext.js +9 -23
- package/package.json +1 -2
- package/src/ValidatedForm.tsx +48 -52
- package/src/hooks.ts +15 -26
- package/src/internal/getInputProps.ts +4 -14
- package/src/internal/hooks.ts +60 -72
- package/src/internal/hydratable.ts +28 -0
- package/src/internal/logic/getCheckboxChecked.ts +10 -0
- package/src/internal/logic/getRadioChecked.ts +7 -0
- package/src/internal/state/atomUtils.ts +13 -0
- package/src/internal/state.ts +99 -177
- package/src/unreleased/formStateHooks.ts +113 -0
- package/src/userFacingFormContext.ts +14 -53
package/src/internal/state.ts
CHANGED
@@ -1,210 +1,132 @@
|
|
1
1
|
import { atom } from "jotai";
|
2
|
-
import { atomWithImmer } from "jotai/immer";
|
3
2
|
import { atomFamily, selectAtom } from "jotai/utils";
|
4
|
-
import
|
3
|
+
import omit from "lodash/omit";
|
5
4
|
import { FieldErrors, TouchedFields } from "../validation/types";
|
5
|
+
import {
|
6
|
+
fieldAtomFamily,
|
7
|
+
formAtomFamily,
|
8
|
+
InternalFormId,
|
9
|
+
} from "./state/atomUtils";
|
6
10
|
|
7
11
|
export const ATOM_SCOPE = Symbol("remix-validated-form-scope");
|
8
12
|
|
9
|
-
export type
|
10
|
-
// Actual state
|
11
|
-
hydrated: boolean;
|
12
|
-
fieldErrors?: FieldErrors;
|
13
|
-
isSubmitting: boolean;
|
14
|
-
hasBeenSubmitted: boolean;
|
15
|
-
touchedFields: TouchedFields;
|
16
|
-
|
17
|
-
// Populated by the form component
|
13
|
+
export type SyncedFormProps = {
|
18
14
|
formId?: string;
|
19
15
|
action?: string;
|
20
16
|
subaction?: string;
|
21
|
-
defaultValues
|
17
|
+
defaultValues: { [fieldName: string]: any };
|
22
18
|
validateField: (fieldName: string) => Promise<string | null>;
|
23
19
|
registerReceiveFocus: (fieldName: string, handler: () => void) => () => void;
|
24
20
|
};
|
25
21
|
|
26
|
-
export
|
27
|
-
|
28
|
-
export
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
export const isHydratedAtom = formAtomFamily(false);
|
23
|
+
export const isSubmittingAtom = formAtomFamily(false);
|
24
|
+
export const hasBeenSubmittedAtom = formAtomFamily(false);
|
25
|
+
export const fieldErrorsAtom = formAtomFamily<FieldErrors>({});
|
26
|
+
export const touchedFieldsAtom = formAtomFamily<TouchedFields>({});
|
27
|
+
export const formPropsAtom = formAtomFamily<SyncedFormProps>({
|
28
|
+
validateField: () => Promise.resolve(null),
|
29
|
+
registerReceiveFocus: () => () => {},
|
30
|
+
defaultValues: {},
|
31
|
+
});
|
32
|
+
export const formElementAtom = formAtomFamily<HTMLFormElement | null>(null);
|
33
|
+
|
34
|
+
//// Everything below is derived from the above
|
35
|
+
|
36
|
+
export const cleanupFormState = (formId: InternalFormId) => {
|
37
|
+
[
|
38
|
+
isHydratedAtom,
|
39
|
+
isSubmittingAtom,
|
40
|
+
hasBeenSubmittedAtom,
|
41
|
+
fieldErrorsAtom,
|
42
|
+
touchedFieldsAtom,
|
43
|
+
formPropsAtom,
|
44
|
+
].forEach((formAtom) => formAtom.remove(formId));
|
32
45
|
};
|
33
46
|
|
34
|
-
export const
|
35
|
-
|
36
|
-
hydrated: false,
|
37
|
-
isSubmitting: false,
|
38
|
-
hasBeenSubmitted: false,
|
39
|
-
touchedFields: {},
|
40
|
-
|
41
|
-
// The symbol version is just to keep things straight with the `atomFamily`
|
42
|
-
formId: typeof formId === "string" ? formId : undefined,
|
43
|
-
|
44
|
-
// Will change upon hydration -- these will never actually be used
|
45
|
-
validateField: () => Promise.resolve(null),
|
46
|
-
registerReceiveFocus: () => () => {},
|
47
|
-
})
|
47
|
+
export const isValidAtom = atomFamily((formId: InternalFormId) =>
|
48
|
+
atom((get) => Object.keys(get(fieldErrorsAtom(formId))).length === 0)
|
48
49
|
);
|
49
50
|
|
50
|
-
export const
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
export const fieldDefaultValueAtom = (name: string) => (formAtom: FormAtom) =>
|
57
|
-
selectAtom(
|
58
|
-
formAtom,
|
59
|
-
(formState) =>
|
60
|
-
formState.defaultValues && lodashGet(formState.defaultValues, name)
|
61
|
-
);
|
62
|
-
|
63
|
-
// Selector atoms
|
64
|
-
|
65
|
-
export const formSelectorAtom =
|
66
|
-
<T>(selector: (state: FormState) => T) =>
|
67
|
-
(formAtom: FormAtom) =>
|
68
|
-
selectAtom(formAtom, selector);
|
69
|
-
|
70
|
-
export const fieldErrorsAtom = formSelectorAtom((state) => state.fieldErrors);
|
71
|
-
export const touchedFieldsAtom = formSelectorAtom(
|
72
|
-
(state) => state.touchedFields
|
73
|
-
);
|
74
|
-
export const actionAtom = formSelectorAtom((state) => state.action);
|
75
|
-
export const hasBeenSubmittedAtom = formSelectorAtom(
|
76
|
-
(state) => state.hasBeenSubmitted
|
77
|
-
);
|
78
|
-
export const validateFieldAtom = formSelectorAtom(
|
79
|
-
(state) => state.validateField
|
80
|
-
);
|
81
|
-
export const registerReceiveFocusAtom = formSelectorAtom(
|
82
|
-
(state) => state.registerReceiveFocus
|
83
|
-
);
|
84
|
-
export const isSubmittingAtom = formSelectorAtom((state) => state.isSubmitting);
|
85
|
-
export const defaultValuesAtom = formSelectorAtom(
|
86
|
-
(state) => state.defaultValues
|
87
|
-
);
|
88
|
-
export const isValidAtom = formSelectorAtom(
|
89
|
-
(state) => Object.keys(state.fieldErrors ?? {}).length === 0
|
51
|
+
export const resetAtom = atomFamily((formId: InternalFormId) =>
|
52
|
+
atom(null, (_get, set) => {
|
53
|
+
set(fieldErrorsAtom(formId), {});
|
54
|
+
set(touchedFieldsAtom(formId), {});
|
55
|
+
set(hasBeenSubmittedAtom(formId), false);
|
56
|
+
})
|
90
57
|
);
|
91
|
-
export const isHydratedAtom = formSelectorAtom((state) => state.hydrated);
|
92
|
-
|
93
|
-
// Update atoms
|
94
|
-
|
95
|
-
export type FieldAtomArgs = {
|
96
|
-
name: string;
|
97
|
-
formAtom: FormAtom;
|
98
|
-
};
|
99
58
|
|
100
|
-
export const
|
101
|
-
null,
|
102
|
-
|
103
|
-
set(
|
104
|
-
|
105
|
-
return state;
|
106
|
-
})
|
59
|
+
export const startSubmitAtom = atomFamily((formId: InternalFormId) =>
|
60
|
+
atom(null, (_get, set) => {
|
61
|
+
set(isSubmittingAtom(formId), true);
|
62
|
+
set(hasBeenSubmittedAtom(formId), true);
|
63
|
+
})
|
107
64
|
);
|
108
65
|
|
109
|
-
export const
|
110
|
-
null,
|
111
|
-
|
112
|
-
|
113
|
-
if (!state.fieldErrors) state.fieldErrors = {};
|
114
|
-
state.fieldErrors[name] = error;
|
115
|
-
return state;
|
116
|
-
})
|
66
|
+
export const endSubmitAtom = atomFamily((formId: InternalFormId) =>
|
67
|
+
atom(null, (_get, set) => {
|
68
|
+
set(isSubmittingAtom(formId), false);
|
69
|
+
})
|
117
70
|
);
|
118
71
|
|
119
|
-
export const
|
120
|
-
|
121
|
-
|
122
|
-
get,
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
72
|
+
export const setTouchedAtom = atomFamily((formId: InternalFormId) =>
|
73
|
+
atom(
|
74
|
+
null,
|
75
|
+
(get, set, { field, touched }: { field: string; touched: boolean }) => {
|
76
|
+
const prev = get(touchedFieldsAtom(formId));
|
77
|
+
if (prev[field] !== touched) {
|
78
|
+
set(touchedFieldsAtom(formId), {
|
79
|
+
...prev,
|
80
|
+
[field]: touched,
|
81
|
+
});
|
82
|
+
}
|
83
|
+
}
|
84
|
+
)
|
130
85
|
);
|
131
86
|
|
132
|
-
export const
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
87
|
+
export const setFieldErrorAtom = atomFamily((formId: InternalFormId) =>
|
88
|
+
atom(
|
89
|
+
null,
|
90
|
+
(
|
91
|
+
get,
|
92
|
+
set,
|
93
|
+
{ field, error }: { field: string; error: string | undefined }
|
94
|
+
) => {
|
95
|
+
const prev = get(fieldErrorsAtom(formId));
|
96
|
+
if (error === undefined && field in prev) {
|
97
|
+
set(fieldErrorsAtom(formId), omit(prev, field));
|
98
|
+
}
|
99
|
+
|
100
|
+
if (error !== undefined && prev[field] !== error) {
|
101
|
+
set(fieldErrorsAtom(formId), {
|
102
|
+
...get(fieldErrorsAtom(formId)),
|
103
|
+
[field]: error,
|
104
|
+
});
|
105
|
+
}
|
106
|
+
}
|
107
|
+
)
|
143
108
|
);
|
144
109
|
|
145
|
-
|
146
|
-
null,
|
147
|
-
(get, set, { formAtom }: { formAtom: FormAtom }) => {
|
148
|
-
set(formAtom, (state) => {
|
149
|
-
state.fieldErrors = {};
|
150
|
-
state.touchedFields = {};
|
151
|
-
state.hasBeenSubmitted = false;
|
152
|
-
return state;
|
153
|
-
});
|
154
|
-
}
|
155
|
-
);
|
110
|
+
//// Field specific
|
156
111
|
|
157
|
-
export const
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
});
|
165
|
-
}
|
112
|
+
export const fieldTouchedAtom = fieldAtomFamily(({ formId, field }) =>
|
113
|
+
atom(
|
114
|
+
(get) => get(touchedFieldsAtom(formId))[field],
|
115
|
+
(_get, set, touched: boolean) => {
|
116
|
+
set(setTouchedAtom(formId), { field, touched });
|
117
|
+
}
|
118
|
+
)
|
166
119
|
);
|
167
120
|
|
168
|
-
export const
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
}
|
121
|
+
export const fieldErrorAtom = fieldAtomFamily(({ formId, field }) =>
|
122
|
+
atom(
|
123
|
+
(get) => get(fieldErrorsAtom(formId))[field],
|
124
|
+
(_get, set, error: string | undefined) => {
|
125
|
+
set(setFieldErrorAtom(formId), { field, error });
|
126
|
+
}
|
127
|
+
)
|
176
128
|
);
|
177
129
|
|
178
|
-
|
179
|
-
|
180
|
-
action?: string;
|
181
|
-
subaction?: string;
|
182
|
-
validateField: FormState["validateField"];
|
183
|
-
registerReceiveFocus: FormState["registerReceiveFocus"];
|
184
|
-
formAtom: FormAtom;
|
185
|
-
};
|
186
|
-
export const syncFormContextAtom = atom(
|
187
|
-
null,
|
188
|
-
(
|
189
|
-
get,
|
190
|
-
set,
|
191
|
-
{
|
192
|
-
defaultValues,
|
193
|
-
action,
|
194
|
-
subaction,
|
195
|
-
formAtom,
|
196
|
-
validateField,
|
197
|
-
registerReceiveFocus,
|
198
|
-
}: SyncFormContextArgs
|
199
|
-
) => {
|
200
|
-
set(formAtom, (state) => {
|
201
|
-
state.defaultValues = defaultValues;
|
202
|
-
state.action = action;
|
203
|
-
state.subaction = subaction;
|
204
|
-
state.registerReceiveFocus = registerReceiveFocus;
|
205
|
-
state.validateField = validateField;
|
206
|
-
state.hydrated = true;
|
207
|
-
return state;
|
208
|
-
});
|
209
|
-
}
|
130
|
+
export const fieldDefaultValueAtom = fieldAtomFamily(({ formId, field }) =>
|
131
|
+
selectAtom(formPropsAtom(formId), (state) => state.defaultValues[field])
|
210
132
|
);
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import { useMemo } from "react";
|
2
|
+
import {} from "../internal/getInputProps";
|
3
|
+
import {
|
4
|
+
useInternalFormContext,
|
5
|
+
useClearError,
|
6
|
+
useSetTouched,
|
7
|
+
useDefaultValuesForForm,
|
8
|
+
useFieldErrorsForForm,
|
9
|
+
useFormAtomValue,
|
10
|
+
} from "../internal/hooks";
|
11
|
+
import {
|
12
|
+
fieldErrorsAtom,
|
13
|
+
formPropsAtom,
|
14
|
+
hasBeenSubmittedAtom,
|
15
|
+
isSubmittingAtom,
|
16
|
+
isValidAtom,
|
17
|
+
touchedFieldsAtom,
|
18
|
+
} from "../internal/state";
|
19
|
+
import { FieldErrors, TouchedFields } from "../validation/types";
|
20
|
+
|
21
|
+
export type FormState = {
|
22
|
+
fieldErrors: FieldErrors;
|
23
|
+
isSubmitting: boolean;
|
24
|
+
hasBeenSubmitted: boolean;
|
25
|
+
touchedFields: TouchedFields;
|
26
|
+
defaultValues: { [fieldName: string]: any };
|
27
|
+
action?: string;
|
28
|
+
subaction?: string;
|
29
|
+
isValid: boolean;
|
30
|
+
};
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Returns information about the form.
|
34
|
+
*
|
35
|
+
* @param formId the id of the form. Only necessary if being used outside a ValidatedForm.
|
36
|
+
*/
|
37
|
+
export const useFormState = (formId?: string): FormState => {
|
38
|
+
const formContext = useInternalFormContext(formId, "useIsValid");
|
39
|
+
const formProps = useFormAtomValue(formPropsAtom(formContext.formId));
|
40
|
+
const isSubmitting = useFormAtomValue(isSubmittingAtom(formContext.formId));
|
41
|
+
const hasBeenSubmitted = useFormAtomValue(
|
42
|
+
hasBeenSubmittedAtom(formContext.formId)
|
43
|
+
);
|
44
|
+
const touchedFields = useFormAtomValue(touchedFieldsAtom(formContext.formId));
|
45
|
+
const isValid = useFormAtomValue(isValidAtom(formContext.formId));
|
46
|
+
|
47
|
+
const defaultValuesToUse = useDefaultValuesForForm(formContext);
|
48
|
+
const hydratedDefaultValues = defaultValuesToUse.hydrateTo(
|
49
|
+
formProps.defaultValues
|
50
|
+
);
|
51
|
+
|
52
|
+
const fieldErrorsFromState = useFormAtomValue(
|
53
|
+
fieldErrorsAtom(formContext.formId)
|
54
|
+
);
|
55
|
+
const fieldErrorsToUse = useFieldErrorsForForm(formContext);
|
56
|
+
const hydratedFieldErrors = fieldErrorsToUse.hydrateTo(fieldErrorsFromState);
|
57
|
+
|
58
|
+
return useMemo(
|
59
|
+
() => ({
|
60
|
+
...formProps,
|
61
|
+
defaultValues: hydratedDefaultValues,
|
62
|
+
fieldErrors: hydratedFieldErrors ?? {},
|
63
|
+
hasBeenSubmitted,
|
64
|
+
isSubmitting,
|
65
|
+
touchedFields,
|
66
|
+
isValid,
|
67
|
+
}),
|
68
|
+
[
|
69
|
+
formProps,
|
70
|
+
hasBeenSubmitted,
|
71
|
+
hydratedDefaultValues,
|
72
|
+
hydratedFieldErrors,
|
73
|
+
isSubmitting,
|
74
|
+
isValid,
|
75
|
+
touchedFields,
|
76
|
+
]
|
77
|
+
);
|
78
|
+
};
|
79
|
+
|
80
|
+
export type FormHelpers = {
|
81
|
+
/**
|
82
|
+
* Clear the error of the specified field.
|
83
|
+
*/
|
84
|
+
clearError: (fieldName: string) => void;
|
85
|
+
/**
|
86
|
+
* Validate the specified field.
|
87
|
+
*/
|
88
|
+
validateField: (fieldName: string) => Promise<string | null>;
|
89
|
+
/**
|
90
|
+
* Change the touched state of the specified field.
|
91
|
+
*/
|
92
|
+
setTouched: (fieldName: string, touched: boolean) => void;
|
93
|
+
};
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Returns helpers that can be used to update the form state.
|
97
|
+
*
|
98
|
+
* @param formId the id of the form. Only necessary if being used outside a ValidatedForm.
|
99
|
+
*/
|
100
|
+
export const useFormHelpers = (formId?: string): FormHelpers => {
|
101
|
+
const formContext = useInternalFormContext(formId, "useFormHelpers");
|
102
|
+
const setTouched = useSetTouched(formContext);
|
103
|
+
const { validateField } = useFormAtomValue(formPropsAtom(formContext.formId));
|
104
|
+
const clearError = useClearError(formContext);
|
105
|
+
return useMemo(
|
106
|
+
() => ({
|
107
|
+
setTouched,
|
108
|
+
validateField,
|
109
|
+
clearError,
|
110
|
+
}),
|
111
|
+
[clearError, setTouched, validateField]
|
112
|
+
);
|
113
|
+
};
|
@@ -1,23 +1,7 @@
|
|
1
1
|
import { useCallback } from "react";
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
|
5
|
-
useContextSelectAtom,
|
6
|
-
useDefaultValuesForForm,
|
7
|
-
useFieldErrorsForForm,
|
8
|
-
useHydratableSelector,
|
9
|
-
useInternalFormContext,
|
10
|
-
useSetTouched,
|
11
|
-
} from "./internal/hooks";
|
12
|
-
import {
|
13
|
-
actionAtom,
|
14
|
-
defaultValuesAtom,
|
15
|
-
fieldErrorsAtom,
|
16
|
-
hasBeenSubmittedAtom,
|
17
|
-
registerReceiveFocusAtom,
|
18
|
-
touchedFieldsAtom,
|
19
|
-
validateFieldAtom,
|
20
|
-
} from "./internal/state";
|
2
|
+
import { useFormAtomValue, useInternalFormContext } from "./internal/hooks";
|
3
|
+
import { formPropsAtom } from "./internal/state";
|
4
|
+
import { useFormHelpers, useFormState } from "./unreleased/formStateHooks";
|
21
5
|
import { FieldErrors, TouchedFields } from "./validation/types";
|
22
6
|
|
23
7
|
export type FormContextValue = {
|
@@ -76,34 +60,17 @@ export type FormContextValue = {
|
|
76
60
|
export const useFormContext = (formId?: string): FormContextValue => {
|
77
61
|
// Try to access context so we get our error specific to this hook if it's not there
|
78
62
|
const context = useInternalFormContext(formId, "useFormContext");
|
63
|
+
const state = useFormState(formId);
|
64
|
+
const {
|
65
|
+
clearError: internalClearError,
|
66
|
+
setTouched,
|
67
|
+
validateField,
|
68
|
+
} = useFormHelpers(formId);
|
79
69
|
|
80
|
-
const
|
81
|
-
|
82
|
-
const hasBeenSubmitted = useContextSelectAtom(
|
83
|
-
context.formId,
|
84
|
-
hasBeenSubmittedAtom
|
85
|
-
);
|
86
|
-
const isValid = useIsValid(formId);
|
87
|
-
const defaultValues = useHydratableSelector(
|
88
|
-
context,
|
89
|
-
defaultValuesAtom,
|
90
|
-
useDefaultValuesForForm(context)
|
91
|
-
);
|
92
|
-
const fieldErrors = useHydratableSelector(
|
93
|
-
context,
|
94
|
-
fieldErrorsAtom,
|
95
|
-
useFieldErrorsForForm(context)
|
96
|
-
);
|
97
|
-
|
98
|
-
const setFieldTouched = useSetTouched(context);
|
99
|
-
const touchedFields = useContextSelectAtom(context.formId, touchedFieldsAtom);
|
100
|
-
const validateField = useContextSelectAtom(context.formId, validateFieldAtom);
|
101
|
-
const registerReceiveFocus = useContextSelectAtom(
|
102
|
-
context.formId,
|
103
|
-
registerReceiveFocusAtom
|
70
|
+
const { registerReceiveFocus } = useFormAtomValue(
|
71
|
+
formPropsAtom(context.formId)
|
104
72
|
);
|
105
73
|
|
106
|
-
const internalClearError = useClearError(context);
|
107
74
|
const clearError = useCallback(
|
108
75
|
(...names: string[]) => {
|
109
76
|
names.forEach((name) => {
|
@@ -114,16 +81,10 @@ export const useFormContext = (formId?: string): FormContextValue => {
|
|
114
81
|
);
|
115
82
|
|
116
83
|
return {
|
117
|
-
|
118
|
-
|
119
|
-
isValid,
|
120
|
-
defaultValues,
|
121
|
-
clearError,
|
122
|
-
fieldErrors: fieldErrors ?? {},
|
123
|
-
action,
|
124
|
-
setFieldTouched,
|
125
|
-
touchedFields,
|
84
|
+
...state,
|
85
|
+
setFieldTouched: setTouched,
|
126
86
|
validateField,
|
87
|
+
clearError,
|
127
88
|
registerReceiveFocus,
|
128
89
|
};
|
129
90
|
};
|