Realtime value check in Form

Requirement

when user input the front, on background, we need to check this word whether in database. If exists, show warning message under the front.

Overview of the Solution

We’ll modify the CardForm component to perform an asynchronous check whenever the user types in the “front” input. To avoid sending a request to your database on every single keystroke, we will “debounce” the input. This means we’ll wait for the user to stop typing for a brief moment before sending the validation request.

The validation logic itself will be passed to the form as a new prop, onCheckFront. This keeps the CardForm component reusable and separates the form’s UI from the specific database logic.

If the check finds that the word already exists, we will use react-hook-form’s built-in setError function to display a warning message right under the input field.

Implement the Validation Logic in the Form

Next, we’ll use react-hook-form’s watch utility combined with React’s useEffect hook to implement the debounced check.

Here is the complete, updated CardForm.tsx file. The new code is clearly marked with comments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
// Watch the 'front' field for changes
const frontValue = form.watch('front');

React.useEffect(() => {
// If there's no handler or the field is empty, do nothing.
if (!onCheckFront || !frontValue) {
return;
}

// Set a timer to delay the check.
const handler = setTimeout(async () => {
// Don't check if it's the initial default value for an existing card
if (id && frontValue === defaultValues?.front) {
form.clearErrors('front'); // Clear any previous errors
return;
}

const existsData = await onCheckFront(frontValue);

const exists = await existsData.json();

if (exists.result) {
// If the word exists, set a custom error on the 'front' field.
form.setError('front', {
type: 'manual',
message: 'This word already exists in your collection.',
});
} else {
// If the word does not exist, clear the error.
// This is important for when the user corrects the input.
form.clearErrors('front');
}
}, 500); // 500ms delay - adjust as needed

// Cleanup: Clear the timer if the component unmounts or the value changes.
return () => {
clearTimeout(handler);
};
}, [frontValue, onCheckFront, form.setError, form.clearErrors, id, defaultValues?.front]);

Implement onCheckFront Function

Now, in the parent component where you use <CardForm>, you will pass the onCheckFront function. This is where you’ll define how to check your database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { client } from "@/utility/hono";
...
const handleCheckFront = async (slug: string): Promise<CheckCardResultType> => {
const res = client.cards.check[":slug"].$get({
param: { slug },
query: { bundleId: bundleId! }
});

return res;
};
...
<CardForm
onSubmit={onSubmit}
onGenerate={onGenerate}
onCheckFront={handleCheckFront}
disabled={mutation.isPending}
/>
...

Author:Bearalise
Source:Realtime value check in Form

请我喝杯咖啡吧~

支付宝
微信