The problem arises because the validate function in react-hook-form does not handle asynchronous operations well when combined with state updates from react-query. As a result, the hasErrors value does not get updated immediately due to the asynchronous nature of React state updates. To address this issue, we can use a useEffect hook to manage the form errors based on the react-query state.
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useQuery } from 'react-query';
import './index.css';
export function App() {
const {
register,
setError,
clearErrors,
formState: { errors },
getValues,
} = useForm({
mode: 'onChange',
});
const { data, refetch, isError, isRefetchError, isLoadingError } = useQuery(
'repoData',
() => fetch(getValues('example')).then((res) => res.json()),
{
enabled: false,
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
retry: false,
}
);
const hasErrors = isError || isRefetchError || isLoadingError;
const validate = async (value: string) => {
if (value.length > 3) {
await refetch();
// The validation function here does not return any validation result because errors are handled via useEffect
return true;
}
return true;
};
useEffect(() => {
const value = getValues('example');
if (value && value.length > 3) {
if (hasErrors) {
setError('example', {
type: 'manual',
message: `Validation hasErrors value: ${JSON.stringify(hasErrors)}`,
});
} else {
clearErrors('example');
}
}
}, [hasErrors, setError, clearErrors, getValues]);
return (
<>
<h1>Input Validation Bug</h1>
<form>
<input
defaultValue="https://jsonplaceholder.typicode.com/todos/1"
{...register('example', { validate })}
placeholder="Enter any public API URL"
/>
{errors.example && <p>{errors.example?.message}</p>}
<span>
Actual hasErrors value: <b>{JSON.stringify(hasErrors)}</b>
</span>
</form>
<pre>{JSON.stringify(data, null, 2)}</pre>
</>
);
}
Work with our skilled React developers to accelerate your project and boost its performance.
Hire Reactjs Developers