diff --git a/examples/react/next-server-actions/src/app/action.ts b/examples/react/next-server-actions/src/app/action.ts index 8ffa3fc02..2efca028b 100644 --- a/examples/react/next-server-actions/src/app/action.ts +++ b/examples/react/next-server-actions/src/app/action.ts @@ -9,9 +9,8 @@ import { formOpts } from './shared-code' const serverValidate = createServerValidate({ ...formOpts, onServerValidate: ({ value }) => { - if (value.age < 12) { - return 'Server validation: You must be at least 12 to sign up' - } + if (value.age < 12) + return { age: 'Server validation: You must be at least 12 to sign up' } }, }) diff --git a/examples/react/next-server-actions/src/app/client-component.tsx b/examples/react/next-server-actions/src/app/client-component.tsx index b7e62909c..a7104e555 100644 --- a/examples/react/next-server-actions/src/app/client-component.tsx +++ b/examples/react/next-server-actions/src/app/client-component.tsx @@ -3,7 +3,6 @@ import { useActionState } from 'react' import { mergeForm, useForm, useTransform } from '@tanstack/react-form' import { initialFormState } from '@tanstack/react-form/nextjs' -import { useStore } from '@tanstack/react-store' import someAction from './action' import { formOpts } from './shared-code' @@ -18,14 +17,8 @@ export const ClientComp = () => { ), }) - const formErrors = useStore(form.store, (formState) => formState.errors) - return (
form.handleSubmit()}> - {formErrors.map((error) => ( -

{error}

- ))} - { + void (Object.values(this.fieldInfo) as FieldInfo[]).forEach( + (field) => { + const fieldInstance = field.instance + + if (!fieldInstance) return + + if (fieldInstance.name in serverErrorMap) { + fieldInstance.setMeta((prev) => ({ + ...prev, + errorMap: { + ...prev.errorMap, + onServer: serverErrorMap[fieldInstance.name], + }, + })) + fieldInstance.mount() + } + + this.validateField(fieldInstance.name, 'server') + }, + ) + }) } return state @@ -1388,6 +1413,20 @@ export class FormApi< }, })) } + + /** + * when we have an error for onServer in the state, we want + * to clear the error as soon as the user changes the value in the field + */ + if (cause !== 'server') { + this.baseStore.setState((prev) => ({ + ...prev, + errorMap: { + ...prev.errorMap, + onServer: undefined, + }, + })) + } }) return { hasErrored, fieldsErrorMap: currentValidationErrorMap } @@ -1774,6 +1813,7 @@ export class FormApi< // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition ...prev?.errorMap, onMount: undefined, + onServer: undefined, }, })) } diff --git a/packages/react-form/src/nextjs/createServerValidate.ts b/packages/react-form/src/nextjs/createServerValidate.ts index adaa4de1f..2b2934494 100644 --- a/packages/react-form/src/nextjs/createServerValidate.ts +++ b/packages/react-form/src/nextjs/createServerValidate.ts @@ -104,12 +104,25 @@ export const createServerValidate = : onServerError ) as UnwrapFormAsyncValidateOrFn + // Extract string values from errors if they're in object format + const errorsArray = onServerErrorVal + ? Array.isArray(onServerErrorVal) + ? onServerErrorVal.map((err) => + typeof err === 'object' ? Object.values(err)[0] : err, + ) + : [ + typeof onServerErrorVal === 'object' + ? Object.values(onServerErrorVal)[0] + : onServerErrorVal, + ] + : [] + const formState: ServerFormState = { errorMap: { onServer: onServerError, }, values, - errors: onServerErrorVal ? [onServerErrorVal] : [], + errors: errorsArray, } throw new ServerValidateError({