React-Hook-Form Version Number
7.51.2
The issue
When using react-hook-forms
useFormContext
with this component:
TextInput
import { useFormContext } from "react-hook-form";
import { get } from "lodash";
export const TextInput = ({
name,
placeholder,
disabled = false,
}) => {
const { register, formState } = useFormContext();
const field = register(name, {
maxLength: { value: 5, message: "Too Long" },
});
const error = get(formState.errors, name);
const label = error ? <label>{error.message}</label> : null;
return (
<div>
<input
data-testid={`form-input-${name}`}
type="text"
autoComplete="off"
placeholder={placeholder}
readOnly={disabled}
{...field}
/>
{label}
</div>
);
};
Properly wrapped in the Provider (the div
s wrapping the inputs are styled removed it for visual clarity):
import { FormProvider, useForm } from "react-hook-form";
import { TextInput } from "./TextInput";
import { Submit } from "./Submit";
export const Form = ({ onSubmit, initialValues }) => {
const methods = useForm({ defaultValues: initialValues });
const submitFunction = methods.handleSubmit(onSubmit);
return (
<FormProvider {...methods}>
<form onSubmit={submitFunction}>
<div>
<div>
<TextInput
name="name"
placeholder="Name"
/>
</div>
</div>
<Submit
onClick={submitFunction}
isFormValid={methods.formState.isValid}
/>
</form>
</FormProvider>
);
};
For whatever reason the errors in formState: {errors}
does not update onChange
/onBlur
/onFocus
. Despite the formState : {isValid}
updating when the validation returns invalid.
Thru my investigations I noticed that if I update the change handler to
const handleChange = async (e) => {
await trigger(fieldName)
await onChange(e)
}
Where onChange
and trigger
come from react-hook-form
.
Then the errors object gets updated properly.
I have made a Code Sandbox illustrating it:
https://codesandbox.io/p/sandbox/cool-lalande-8n2kxp
Any help with getting it to work without hacking it to force the manual validation trigger, would be appreciated. Maybe the structure of what I am doing is wrong somewhere? I am honestly at a loss here.
2
Answers
It’s because the default mode is
onSubmit
, so that error messages are only shown after the user has submitted. You’re disabling the submit button (which I might add is somewhat of a bad practice), so the error messages will never be shown to the user unless you change the mode something other thanonSubmit
such as:onBlur
onChange
onTouched
all
tl;dr – If you add
mode:all
touseForm()
then it worksSee the modified codesandbox:
https://codesandbox.io/p/sandbox/cool-lalande-forked-xxtpd9?file=%2Fsrc%2FForm.jsx
The reason is the mode. You should change it to the following
If you want to check the errors, it’s good to use
watch
method in the react-hook-form