Skip to content

Commit

Permalink
Execute preventDefault only on invalid in handleSubmit for progressiv…
Browse files Browse the repository at this point in the history
…e enhancement (#11078)

* feat: execute preventDefault only on invalid

* chore: update example

* chore: update remix-form example

* chore: update remix-form example

* chore: update remix-form example

* chore: update remix-form example

* chore: update remix-form example

* chore: update examples

* chore: update hookform packages
  • Loading branch information
kotarella1110 committed Nov 10, 2023
1 parent ef17e17 commit ca6e9b0
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 37 deletions.
6 changes: 3 additions & 3 deletions examples/remix-form/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Form, useActionData } from '@remix-run/react';
import { setTimeout } from 'timers/promises';
import { createActionValidator } from 'react-hook-form/server';
import { useForm } from 'react-hook-form';
import { zodResolver } from '../../node_modules/@hookform/resolvers/zod';
import { zodResolverSync } from '../../node_modules/@hookform/resolvers/zod';
import { z } from 'zod';

export const meta: MetaFunction = () => {
Expand All @@ -28,7 +28,7 @@ export async function action({ request }: ActionFunctionArgs) {
await setTimeout(1000);

const validator = createActionValidator(formData, {
resolver: zodResolver(schema),
resolver: zodResolverSync(schema),
});

await validator.validate();
Expand Down Expand Up @@ -84,7 +84,7 @@ export default function Index() {
username: string;
password: string;
}>({
resolver: zodResolver(schema),
resolver: zodResolverSync(schema),
defaultValues: actionData?.values || {
username: '',
password: '',
Expand Down
6 changes: 3 additions & 3 deletions examples/remix-form/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
"type": "module",
"scripts": {
"build": "remix build",
"dev": "remix dev --manual",
"dev": "remix dev",
"start": "remix-serve ./build/index.js",
"typecheck": "tsc"
},
"dependencies": {
"@hookform/resolvers": "https://pkg.csb.dev/react-hook-form/resolvers/commit/bcc797e8/@hookform/resolvers/_pkg.tgz",
"@hookform/resolvers": "https://pkg.csb.dev/react-hook-form/resolvers/commit/2d6d392c/@hookform/resolvers/_pkg.tgz",
"@remix-run/css-bundle": "^2.1.0",
"@remix-run/node": "^2.1.0",
"@remix-run/react": "^2.1.0",
"@remix-run/serve": "^2.1.0",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "https://pkg.csb.dev/react-hook-form/react-hook-form/commit/a827066d/react-hook-form/_pkg.tgz",
"react-hook-form": "https://pkg.csb.dev/react-hook-form/react-hook-form/commit/2c4b3693/react-hook-form/_pkg.tgz",
"zod": "^3.22.4"
},
"devDependencies": {
Expand Down
26 changes: 13 additions & 13 deletions examples/remix-form/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/server-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"lint": "next lint"
},
"dependencies": {
"@hookform/resolvers": "https://pkg.csb.dev/react-hook-form/resolvers/commit/bcc797e8/@hookform/resolvers/_pkg.tgz",
"@hookform/resolvers": "https://pkg.csb.dev/react-hook-form/resolvers/commit/2d6d392c/@hookform/resolvers/_pkg.tgz",
"next": "13.5.5",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "https://pkg.csb.dev/react-hook-form/react-hook-form/commit/a827066d/react-hook-form/_pkg.tgz",
"react-hook-form": "https://pkg.csb.dev/react-hook-form/react-hook-form/commit/2c4b3693/react-hook-form/_pkg.tgz",
"zod": "^3.22.4"
},
"devDependencies": {
Expand Down
26 changes: 13 additions & 13 deletions examples/server-actions/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/server-actions/src/app/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
experimental_useFormStatus as useFormStatus,
} from 'react-dom';
import { useForm } from 'react-hook-form';
import { zodResolver } from '../../node_modules/@hookform/resolvers/zod';
import { zodResolverSync } from '../../node_modules/@hookform/resolvers/zod';

import { login } from '@/app/actions';
import { schema } from '@/app/schema';
Expand Down Expand Up @@ -34,7 +34,7 @@ export function LoginForm() {
username: string;
password: string;
}>({
resolver: zodResolver(schema),
resolver: zodResolverSync(schema),
defaultValues: formState.values,
errors: formState.errors,
progressive: true,
Expand Down
62 changes: 61 additions & 1 deletion src/logic/createFormControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Path,
PathValue,
Ref,
ResolverResult,
SetFieldValue,
SetValueConfig,
Subjects,
Expand Down Expand Up @@ -405,6 +406,18 @@ export function createFormControl<
),
);

const _executeSchemaSync = (name?: InternalFieldName[]) =>
_options.resolver!(
_formValues as TFieldValues,
_options.context,
getResolverOptions(
name || _names.mount,
_fields,
_options.criteriaMode,
_options.shouldUseNativeValidation,
),
) as ResolverResult<TFieldValues>;

const executeSchemaAndUpdateState = async (names?: InternalFieldName[]) => {
const { errors } = await _executeSchema(names);

Expand Down Expand Up @@ -1139,6 +1152,53 @@ export function createFormControl<
});
};

const handleSubmitSync: UseFormHandleSubmit<TFieldValues> =
(onValid, onInvalid) => async (e) => {
let fieldValues = cloneObject(_formValues);

_subjects.state.next({
isSubmitting: true,
});

if (_options.resolver) {
const { errors, values } = _executeSchemaSync();
_formState.errors = errors;
fieldValues = values;
} else {
// TODO
// executeBuiltInValidationSync(_fields);
}

unset(_formState.errors, 'root');

if (isEmptyObject(_formState.errors)) {
_subjects.state.next({
errors: {},
});
if (onValid) {
await onValid(fieldValues as TFieldValues, e);
}
} else {
if (e) {
e.preventDefault && e.preventDefault();
e.persist && e.persist();
}
if (onInvalid) {
await onInvalid({ ..._formState.errors }, e);
}
_focusError();
setTimeout(_focusError);
}

_subjects.state.next({
isSubmitted: true,
isSubmitting: false,
isSubmitSuccessful: isEmptyObject(_formState.errors),
submitCount: _formState.submitCount + 1,
errors: _formState.errors,
});
};

const resetField: UseFormResetField<TFieldValues> = (name, options = {}) => {
if (get(_fields, name)) {
if (isUndefined(options.defaultValue)) {
Expand Down Expand Up @@ -1384,7 +1444,7 @@ export function createFormControl<
},
trigger,
register,
handleSubmit,
handleSubmit: props.progressive ? handleSubmitSync : handleSubmit,
watch,
setValue,
getValues,
Expand Down

0 comments on commit ca6e9b0

Please sign in to comment.