React Hook Form中errors对象为何会临时变为空对象?
errors object temporarily become empty after setting an error? Let me break down why you're seeing this behavior and how to fix it:
The Root Cause
The issue comes down to two key parts of your code combined with React Hook Form's default behavior:
setValueclears errors by default
When you callsetValue("name", value)inonNameChange, React Hook Form automatically clears any existing errors for thenamefield (this is the default behavior, controlled by theshouldClearErrorsoption which defaults totrue). This immediately emptieserrors.nameas soon as you type a new character.Triggered validation passes initially
Right aftersetValue, you runawait trigger("name"). Since your only validation rule isrequired: true, as long as the new input isn't empty, this validation will pass (returntrue). React Hook Form won't re-add any errors to theerrorsobject at this point.Debounced API call introduces a delay
YourgetPokemonDebouncedfunction has a 500ms delay. During this gap, the API call hasn't failed yet, so you haven't runsetErrorto re-add the custom error. This creates the window whereerrorsis temporarily empty.
Once the debounce delay ends and the API call fails, setError runs and repopulates errors.name with your custom message.
How to Fix It
You have a couple of options depending on your desired behavior:
Option 1: Prevent setValue from clearing errors
Modify your setValue call to disable the default error-clearing behavior by adding the shouldClearErrors: false option:
setValue("name", value, { shouldClearErrors: false });
This way, the existing error stays in place until your API call either succeeds (clearing it) or fails (retaining/updating it).
Option 2: Use React Hook Form's built-in async validation
Instead of manually handling the API call and setError, let RHF handle the async validation directly in the register rules. This eliminates the need for custom onChange logic and debouncing (you can still add debouncing inside the validate function if needed):
<input {...register("name", { required: "Name is required", validate: async (value) => { // Add debounce here if needed try { await axios.get(`https://pokeapi.co/api/v2/pokemon/${value}`); return true; } catch (error) { return "CUSTOM name error"; } } })} name="name" placeholder="Enter a pokemon" />
RHF will automatically manage the error state throughout the validation process, so you won't see the temporary empty errors object.
Walkthrough of Your Scenario
To recap the flow you're seeing:
- You type
wefhiwd→ API fails →setErroraddserrors.name. - You type another character →
setValueclearserrors.name→trigger("name")passes (since input isn't empty) →errorsis empty. - 500ms later → API fails again →
setErrorre-addserrors.name.
内容的提问来源于stack exchange,提问作者user8758206

