I’m building some user inputs for a client-side application with react-hook-form.
Users should be able to update an input. Then onBlur, react-hook-form is to validate the input and update an react useState object. If validation fails, the external state is not updated.
The following code fails to keep the external state object up to date onBlur.
As the handleSubmit() function is async, i’m unable to set the state.
function App() {
const [value, setValue] = useState({
name: "",
});
const { register, handleSubmit } = useForm({ mode: "onBlur" });
return (
<>
{errors?.name ? <p>{errors.name.message}</p> : null}
<label htmlFor="name">Name</label>
<input
{...register("name", {
onBlur: handleSubmit((data) => {
setValue((prev) => ({ ...prev, name: data.name }));
}),
minLength: { value: 2, message: "Name is too short" },
required: { value: true, message: "Name is required" },
})}
id="name"
type="text"
/>
</>
);
}
- I’ve tried wrapping handleSubmit in async / await – however this doesn’t yield anything as the handleSubmit method will only expose the result to the callback function.
- useEffect on the react-hook-form watch() function; issue with this is you dont get the validation.
- Creating my own synchronous methods to validate seem to defeat the purpose of using react-hook-form.
user28682631 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1
updated code — this will work for you.. i have updated the code.
import React, { useState } from "react";
import { useForm } from "react-hook-form";
function App() {
const [value, setValue] = useState({
name: "",
});
const {
register,
trigger,
getValues,
formState: { errors },
} = useForm({ mode: "onBlur" });
const handleBlur = async (fieldName) => {
const isValid = await trigger(fieldName); // Validate the field
if (isValid) {
const fieldValue = getValues(fieldName); // Get the current field value
setValue((prev) => ({ ...prev, [fieldName]: fieldValue }));
}
};
return (
<>
{errors?.name && <p>{errors.name.message}</p>}
<label htmlFor="name">Name</label>
<input
{...register("name", {
onBlur: () => handleBlur("name"), // Call the custom blur handler
minLength: { value: 2, message: "Name is too short" },
required: { value: true, message: "Name is required" },
})}
id="name"
type="text"
/>
</>
);
}
export default App;
Shivam Tiwari is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.