THN Interview Prep

Forms, validation & UX contracts

Forms are where UI state, accessibility, security, backend contracts, and user trust meet. A senior frontend answer treats forms as workflows, not input collections.

Core details

ConcernStrong defaultFailure mode
OwnershipControlled for complex interactive state; uncontrolled/native for simple formstwo sources of truth
ValidationClient for fast feedback, server for authoritytrusting client validation
Timingvalidate on submit, blur, or change based on task costnoisy errors while user is typing
Errorsfield-level + form-level + focus managementred text not associated with inputs
Submitpending state, disabled duplicate action, retry modeldouble charge / duplicate record
Accessibilitylabels, descriptions, aria-invalid, aria-describedbyscreen reader user cannot find errors
Optimistic UIonly when rollback semantics are clearlying about failed writes

Controlled vs uncontrolled: controlled inputs make React state the source of truth and are useful for dependent fields, masks, live previews, and complex validation. Uncontrolled inputs use the DOM as the source of truth and are often simpler for traditional submit flows.

Validation layering: client validation improves speed and clarity; server validation is the security and correctness boundary. Server responses should use stable error shapes that the UI can map to fields.

Async submits: use a single in-flight model, idempotency keys for dangerous writes, and explicit success/failure states. Disabling the submit button alone is not enough because users can reload, double-click before state updates, or retry after a timeout.

Understanding

Good forms reduce uncertainty. Users need to know what is required, what went wrong, what is being saved, whether they can leave, and whether the result succeeded. That means form state must be visible, accessible, and resilient to network ambiguity.

Validation timing is a product decision. Password rules can update as the user types. Credit-card payment failures should wait for submit or provider response. A long enterprise form may validate sections on blur and summarize all errors on submit.

Optimistic UI is appropriate when the user action is likely to succeed and rollback is understandable. It is risky for irreversible or regulated actions. For financial, security, or inventory-sensitive writes, prefer pending states and confirmed success.

Practical examples

Accessible field error:

<label htmlFor="email">Email</label>
<input
  id="email"
  name="email"
  type="email"
  aria-invalid={Boolean(errors.email)}
  aria-describedby={errors.email ? "email-error" : undefined}
/>
{errors.email ? <p id="email-error">{errors.email}</p> : null}

Server-friendly error shape:

type FormResult =
  | { ok: true; id: string }
  | {
      ok: false;
      formError?: string;
      fieldErrors?: Record<string, string>;
    };

Submit flow:

  1. Generate or reuse an idempotency key for dangerous writes.
  2. Disable repeat submit affordance and show pending state.
  3. Keep field values stable while pending.
  4. On validation failure, move focus to the first invalid field or error summary.
  5. On ambiguous network failure, explain whether retry is safe.

Senior understanding

ProbeStrong answer
“Controlled or uncontrolled?”Choose by state complexity, performance, and integration needs
“Client validation enough?”No; server validates all authoritative rules
“Optimistic submit?”Only with rollback/error model and product permission
“Duplicate submit?”Idempotency key plus server-side dedupe for risky writes
“A11y done?”Labels, error association, focus, keyboard, live status

Failure modes

  • Showing errors only through color.
  • Clearing all fields after a failed submit.
  • Using placeholder text as the only label.
  • Running expensive validation on every keystroke without debouncing.
  • Letting a slow failed response overwrite a newer successful submit state.
  • Trusting disabled buttons as duplicate-write prevention.

Diagram

Loading diagram…

See also

Spotted something unclear or wrong on this page?

On this page