After this lesson, you will be able to: Use controlled vs uncontrolled inputs; react-hook-form + Zod for production forms.
Forms are 80% of frontend bugs. The right library saves real hours.
Trade-offs.
// Controlled: state is in React; input renders FROM stateconst [name, setName] = useState("");<input value={name} onChange={(e) => setName(e.target.value)} />// Uncontrolled: state in the DOM; React reads via refconst inputRef = useRef<HTMLInputElement>(null);<input ref={inputRef} defaultValue="" />// Read on submit: inputRef.current.value// Controlled wins for: realtime validation, formatting, conditional rendering.// Uncontrolled wins for: performance on big forms (no re-render per keystroke).
Uncontrolled under the hood; ergonomic API.
import { useForm } from "react-hook-form";import { zodResolver } from "@hookform/resolvers/zod";import { z } from "zod";const Schema = z.object({email: z.string().email(),password: z.string().min(8),});type FormData = z.infer<typeof Schema>;function LoginForm() {const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<FormData>({resolver: zodResolver(Schema),});return (<form onSubmit={handleSubmit(async (data) => await login(data))}><input {...register("email")} />{errors.email && <p>{errors.email.message}</p>}<input type="password" {...register("password")} />{errors.password && <p>{errors.password.message}</p>}<button disabled={isSubmitting}>Sign in</button></form>);}
Every input has a label (`<label htmlFor>` or wrapping). Error messages linked via aria-describedby. Submit button accessible (real `<button type="submit">`). Don't disable submit only on validation error, set aria-invalid + show error.
Hand-rolling form state with 10 useStates. RHF takes 10 minutes to learn; saves days. Forgetting to disable submit during in-flight requests. Users double-click. Validating only on submit. Real-time validation (after blur) gives better UX. No labels. Accessibility AND form autofill break.
Pick the senior answer.
Sign in and purchase access to unlock this lesson.