Exercise: debouncing (Zod, tRPC, fetch in useEffect)
Goal
Practice debouncing in three common places:
- Zod form validation on change
- tRPC “availability check” calls
- plain
fetchinsideuseEffectfor search/autocomplete
Part A — Debounced Zod validation (client-side UX)
Build (or extend) a form field (e.g. Email) that:
- validates with Zod
- validates on change, debounced
- still validates on submit as the final gate
Acceptance criteria:
- Validation does not run on every keystroke (it’s delayed).
- Errors do not “flash” while the user is typing normally.
- Clearing the field clears the error state appropriately.
Part B — Debounced tRPC availability check
Simulate an “is email taken?” check:
- When the email looks valid, call a tRPC query (or a mocked function standing in for it).
- Debounce the call.
- Handle these states in the UI:
- idle (no check yet)
- checking
- available
- taken
- error
Acceptance criteria:
- Only the latest typed value can win (stale results must be ignored).
- Changing the email cancels/invalidates the previous in-flight check.
- No call is made for obviously invalid input (basic gating before calling).
Part C — Debounced fetch in useEffect (search/autocomplete)
Create a search box that:
- triggers a
fetchin an effect when the query changes - debounces the effect
- handles cancellation/ignoring stale results (e.g.
AbortControlleror a request id)
Acceptance criteria:
- Typing quickly does not fire a request per keystroke.
- Stale results never replace newer ones.
- Empty query shows an intentional empty state.
Notes (keep it simple)
- Debouncing is about timing; stale-result handling is about correctness.
- Prefer gating before calling the network (format checks, min length, etc.).
Last updated on