Good morning,
I am studying the React 18 course for Beginners. I am in the Building Forms module, video 14 – Integrating React Hook form and Zod.
I set up everything in ExpenseForm.tsx as in the video, but my form validation does not show any error messages. It seems that these lines of code have some issue….
{errors.description && <p className="text-danger">{errors.description.message}</p>}
…
{errors.amount && <p className="text-danger">{errors.amount.message}</p>}
…
{errors.category&& <p className="text-danger">{errors.category.message}</p>}
Anybody knows why the messages do not appear?
Here is my full code for the ExpenseForm component of the ExpenseTracker app.
import {z} from ‘zod’;
import {useForm} from ‘react-hook-form’;
import {zodResolver } from ‘@hookform/resolvers/zod’;
import categories from ‘../categories’;
const schema = z.object({
description: z.string().min(3, {message: "Description should be at least 3 characters."}).max(50),
amount: z.number({invalid_type_error: "Amount is required."}).min(0.01).max(100_000),
category: z.enum(categories, {
errorMap: () => ({message: "Category is required."})
})
});
type ExpenseFormData = z.infer;
const ExpenseForm = () => {
const {register, handleSubmit, formState: {errors}} = useForm<ExpenseFormData>({resolver: zodResolver(schema)});
return (
<form >
<div className="mb-3">
<label htmlFor="description" className="form-label">Description</label>
<input {...register("description")} id="description" type="text" className="form-control" />
{errors.description && <p className="text-danger">{errors.description.message}</p>}
</div>
<div className="mb-3">
<label htmlFor="amount" className="form-label">Amount</label>
<input {...register("amount", {valueAsNumber: true})} id="amount" type="number" className="form-control" />
{errors.amount && <p className="text-danger">{errors.amount.message}</p>}
</div>
<div className="mb-3">
<label htmlFor="category" className="form-label">Category</label>
<select {...register("category")} id="category" className="form-select" >
<option value = ""></option>
{categories.map(category => <option key={category} value = {category}>{category}</option>)}
</select>
{errors.category && <p className="text-danger">{errors.category.message}</p>}
</div>
<button className="btn btn-primary">Submit</button>
</form>
)
}
export default ExpenseForm