Use Cases (अपडेट: 2/6/2026)

Claude Code से React Hook Form सुरक्षित तरीके से बनाना

useForm, Zod validation, error display, submit state, tests और सुरक्षित Claude Code prompts के साथ React forms बनाएं।

Claude Code से React Hook Form सुरक्षित तरीके से बनाना

Claude Code को काम देने से पहले form contract तय करें

React Hook Form, React में forms बनाने के लिए हल्की और practical library है। हर keystroke को useState में रखने की जगह यह browser के native form behavior का उपयोग करती है और register, handleSubmit, formState जैसे APIs देती है। Beginner के लिए इससे तीन बातें साफ होती हैं: values कहां collect होंगी, validation कब चलेगा, और submit के दौरान button कैसे disable होगा।

Claude Code component, Zod schema, API route, tests और refactor का draft जल्दी बना सकता है। लेकिन form अक्सर business funnel में होता है: contact request, product trial, pre-purchase survey, newsletter signup या profile edit. अगर prompt सिर्फ “एक form बना दो” है, तो output देखने में सही हो सकता है पर accessible error messages, server-side validation या reliable submit state छूट सकते हैं।

इस guide में inquiry form के उदाहरण से useForm, zodResolver, field errors, submit state, server revalidation, testability और safe Claude Code prompts समझाए गए हैं। React patterns के लिए Claude Code React development और schema design के लिए Claude Code Zod validation भी देखें।

Architecture: schema को center में रखें

React Hook Form form workflow संभालता है। Zod बताता है कि कौन सा input valid है। @hookform/resolvers/zod का zodResolver दोनों को जोड़ता है, ताकि React Hook Form validation के समय Zod schema चला सके।

flowchart TD
  A["User input करता है"] --> B["React Hook Form register"]
  B --> C["zodResolver schema validate करता है"]
  C --> D{"Input valid है"}
  D -->|नहीं| E["Field errors दिखाएं"]
  D -->|हां| F["handleSubmit values भेजता है"]
  F --> G["API वही schema validate करती है"]
  G --> H["Save, notify या CRM sync"]

सरल भाषा में, useForm form controller है, Zod schema rule book है, और resolver दोनों के बीच adapter है। Claude Code को changes देते समय इन तीन parts को नाम से बताने से accidental rewrite कम होता है। बाद में नया field जोड़ना हो तो prompt में कह सकते हैं: schema, UI, API और tests साथ में update करें।

Official references के लिए React Hook Form का useForm docs, React Hook Form Resolvers, Zod API docs, React का <input> reference, और Claude Code overviewcommands देखें।

Copy-paste Zod schema

Validation rules को अलग file में रखें। नीचे का example name, email, category, message और contact consent संभालता है। z.infer schema से TypeScript type बनाता है, इसलिए type और runtime validation अलग-अलग maintain नहीं करने पड़ते।

// src/features/inquiry/inquirySchema.ts
import { z } from "zod";

export const inquirySchema = z.object({
  name: z
    .string()
    .trim()
    .min(1, "नाम लिखें")
    .max(80, "नाम 80 characters से कम रखें"),
  email: z
    .string()
    .trim()
    .email("Valid email address लिखें"),
  category: z.enum(["consulting", "support", "billing"], {
    error: "Category चुनें",
  }),
  message: z
    .string()
    .trim()
    .min(10, "Message कम से कम 10 characters का होना चाहिए")
    .max(1000, "Message 1000 characters से कम रखें"),
  agreeToContact: z.boolean().refine((value) => value, {
    message: "Contact consent जरूरी है",
  }),
});

export type InquiryFormValues = z.infer<typeof inquirySchema>;

category enum है क्योंकि submitted value stable होनी चाहिए। Real project में यही value lead को sales, support, billing या CRM workflow में भेज सकती है। Claude Code prompt में label और submitted value अलग लिखें, जैसे “label: Technical support, value: support”. Label localize हो सकता है, value stable रहनी चाहिए।

useForm से values, errors और submit state संभालना

नीचे form component है। mode: "onBlur" का मतलब है कि user field छोड़ने पर validation चलेगा। Contact form में यह हर keypress पर error दिखाने से ज्यादा comfortable होता है। Final submit पर handleSubmit फिर से validation करता है।

// src/features/inquiry/InquiryForm.tsx
"use client";

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { inquirySchema, type InquiryFormValues } from "./inquirySchema";

async function sendInquiry(values: InquiryFormValues) {
  const response = await fetch("/api/inquiry", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(values),
  });

  if (!response.ok) {
    throw new Error("Failed to send inquiry");
  }
}

export function InquiryForm() {
  const {
    register,
    handleSubmit,
    reset,
    setError,
    formState: { errors, isSubmitting },
  } = useForm<InquiryFormValues>({
    resolver: zodResolver(inquirySchema),
    mode: "onBlur",
    defaultValues: {
      name: "",
      email: "",
      message: "",
      agreeToContact: false,
    },
  });

  const onSubmit = async (values: InquiryFormValues) => {
    try {
      await sendInquiry(values);
      reset();
    } catch {
      setError("root", {
        type: "server",
        message: "Form भेजा नहीं जा सका। थोड़ी देर बाद फिर कोशिश करें।",
      });
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate>
      <div>
        <label htmlFor="name">नाम</label>
        <input
          id="name"
          autoComplete="name"
          aria-invalid={errors.name ? "true" : "false"}
          aria-describedby={errors.name ? "name-error" : undefined}
          {...register("name")}
        />
        {errors.name && (
          <p id="name-error" role="alert">
            {errors.name.message}
          </p>
        )}
      </div>

      <div>
        <label htmlFor="email">Email</label>
        <input
          id="email"
          type="email"
          autoComplete="email"
          aria-invalid={errors.email ? "true" : "false"}
          aria-describedby={errors.email ? "email-error" : undefined}
          {...register("email")}
        />
        {errors.email && (
          <p id="email-error" role="alert">
            {errors.email.message}
          </p>
        )}
      </div>

      <div>
        <label htmlFor="category">विषय</label>
        <select
          id="category"
          aria-invalid={errors.category ? "true" : "false"}
          aria-describedby={errors.category ? "category-error" : undefined}
          {...register("category")}
        >
          <option value="">चुनें</option>
          <option value="consulting">Implementation consulting</option>
          <option value="support">Technical support</option>
          <option value="billing">Billing या contract</option>
        </select>
        {errors.category && (
          <p id="category-error" role="alert">
            {errors.category.message}
          </p>
        )}
      </div>

      <div>
        <label htmlFor="message">Message</label>
        <textarea
          id="message"
          rows={6}
          aria-invalid={errors.message ? "true" : "false"}
          aria-describedby={errors.message ? "message-error" : undefined}
          {...register("message")}
        />
        {errors.message && (
          <p id="message-error" role="alert">
            {errors.message.message}
          </p>
        )}
      </div>

      <label>
        <input type="checkbox" {...register("agreeToContact")} />
        मैं इस inquiry के बारे में contact किए जाने से सहमत हूं
      </label>
      {errors.agreeToContact && (
        <p role="alert">{errors.agreeToContact.message}</p>
      )}

      {errors.root && <p role="alert">{errors.root.message}</p>}

      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? "भेजा जा रहा है..." : "Inquiry भेजें"}
      </button>
    </form>
  );
}

यहां accessibility जरूरी है। Field में aria-invalid, message में role="alert" और input से error को जोड़ने के लिए aria-describedby है। इससे screen reader users को मदद मिलती है और tests भी साफ लिखे जाते हैं। आगे के लिए Claude Code accessibility देखें।

Server पर भी वही schema validate करें

Client-side validation UX के लिए है, security boundary नहीं। कोई भी browser form bypass करके API call कर सकता है। इसलिए API route में भी वही schema import करके safeParse चलाएं।

// app/api/inquiry/route.ts
import { NextResponse } from "next/server";
import { inquirySchema } from "@/features/inquiry/inquirySchema";

export async function POST(request: Request) {
  const payload = await request.json().catch(() => null);
  const parsed = inquirySchema.safeParse(payload);

  if (!parsed.success) {
    return NextResponse.json(
      {
        error: "Invalid inquiry",
        fields: parsed.error.flatten().fieldErrors,
      },
      { status: 400 },
    );
  }

  // TODO: Database save, email या CRM sync यहां जोड़ें।
  return NextResponse.json({ ok: true });
}

Claude Code से API बनवाते समय कहें: “inquirySchema reuse करें, failure पर 400 और field errors लौटाएं, production email और CRM integration TODO रखें।” Secrets, retry और duplicate handling अलग task होने चाहिए।

Tests से form को सुरक्षित रखें

Form visual check से पूरा verify नहीं होता। कम से कम empty submit, valid submit, server failure और disabled button test करें। Vitest और React Testing Library से errors और fetch call check हो सकते हैं।

// src/features/inquiry/InquiryForm.test.tsx
import { afterEach, expect, test, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { InquiryForm } from "./InquiryForm";

afterEach(() => {
  vi.unstubAllGlobals();
});

test("empty submit पर validation errors दिखते हैं", async () => {
  render(<InquiryForm />);

  await userEvent.click(screen.getByRole("button", { name: "Inquiry भेजें" }));

  expect(await screen.findAllByRole("alert")).toHaveLength(5);
});

test("valid values API को submit होते हैं", async () => {
  const fetchMock = vi.fn().mockResolvedValue(new Response("{}", { status: 200 }));
  vi.stubGlobal("fetch", fetchMock);
  render(<InquiryForm />);

  await userEvent.type(screen.getByLabelText("नाम"), "Masa");
  await userEvent.type(screen.getByLabelText("Email"), "masa@example.com");
  await userEvent.selectOptions(screen.getByLabelText("विषय"), "consulting");
  await userEvent.type(
    screen.getByLabelText("Message"),
    "मैं React Hook Form को सुरक्षित तरीके से लागू करना चाहता हूं।",
  );
  await userEvent.click(
    screen.getByLabelText("मैं इस inquiry के बारे में contact किए जाने से सहमत हूं"),
  );
  await userEvent.click(screen.getByRole("button", { name: "Inquiry भेजें" }));

  expect(fetchMock).toHaveBeenCalledWith(
    "/api/inquiry",
    expect.objectContaining({ method: "POST" }),
  );
});

Claude Code को कह सकते हैं कि पहले failing tests लिखे, फिर implementation करे। Full browser flow के लिए Claude Code Playwright testing देखें। Business tracking में event API success के बाद भेजें, button click पर नहीं; यह Claude Code analytics से जुड़ता है।

Safe Claude Code prompt

अच्छे prompt में scope, constraints, verification और non-goals शामिल होते हैं।

React Hook Form और Zod से inquiry form implement करें।

Scope:
- केवल src/features/inquiry और app/api/inquiry बदलें।
- useForm, zodResolver और schema-derived TypeScript types इस्तेमाल करें।
- Fields: name, email, category, message, agreeToContact.
- Field errors role="alert" और aria-describedby से दिखाएं।
- isSubmitting true हो तो submit button disable करें।
- API route में वही Zod schema safeParse करें।
- Vitest + Testing Library tests जोड़ें।

Verification:
- npm test -- InquiryForm
- npm run typecheck

Do not:
- नई UI library न जोड़ें।
- existing category values rename न करें।
- इस task में real email, CRM या secrets implement न करें।

Change request भी specific रखें। “एक category जोड़ो” के बजाय लिखें: “label Training request, value training; schema enum, select, API validation, tests और analytics mapping update करें।” Claude Code files खोज सकता है, लेकिन contract इंसान को define करना चाहिए।

Use cases और design difference

Use caseअच्छा structureध्यान रखें
Contact formZod + React Hook Form + API revalidationButton click नहीं, successful lead measure करें
Profile editCurrent data को defaultValues में डालेंSave के बाद reset(savedValues) करें
Pre-purchase surveyselect, radio, checkbox मिलाएंValues को product या CRM IDs से align करें
Admin searchहल्की validation और URL query syncहर keypress पर API call न करें

Common rule यह है कि UI label और submitted value अलग रखें। Label translate हो सकता है, लेकिन submitted value stable होनी चाहिए क्योंकि reports, automation और backend उस पर निर्भर करते हैं।

Common pitfalls

पहला pitfall है केवल browser में validation करना। API route में shared schema import करें और payload process करने से पहले safeParse चलाएं।

दूसरा है isSubmitting का जल्दी false हो जाना। अगर onSubmit async work को await नहीं करता, तो button जल्दी enable हो सकता है।

तीसरा है error को field से दूर दिखाना। Top banner helpful हो सकता है, लेकिन हर field के पास अपना message होना चाहिए।

चौथा है Claude Code को नया design system बना देने देना। अगर app में TextField, Select, Button या toast पहले से हैं, prompt में reuse करने को कहें।

पांचवां है submit के बाद का रास्ता भूलना: success message, thank-you page, email, analytics event और CRM sync plan करें।

Monetization CTA

Form quality को funnel से मापें। Goal क्या है: PDF signup, product lead, paid template purchase या consulting request? Goal तय करने के बाद Claude Code से fields कम करवाना, error copy सुधारना या tests जोड़ना ज्यादा असरदार होता है।

Self-study के लिए products देखें। Team workflow में Claude Code forms लागू करने के लिए training and consulting से शुरुआत करें। Form छोटा component है, लेकिन useful content और revenue के बीच अक्सर यही gate होता है।

Tested result note

Masa ने इस pattern को छोटे inquiry flow में test किया। सबसे उपयोगी बदलाव schema को एक file में रखना था, क्योंकि इससे UI में option जोड़कर API allowed values भूलने वाली गलती रुकी। Empty submit और valid submit tests भी उपयोगी रहे। Claude Code से follow-up edit करवाने के बाद उन्हीं tests ने missing error message और टूटी हुई fetch call जल्दी पकड़ ली। Practical maintenance में form को सिर्फ UI नहीं, input contract मानना ज्यादा सुरक्षित है।

#Claude Code #React Hook Form #React #forms #validation
मुफ़्त

मुफ़्त PDF: Claude Code cheatsheet

Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.

हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.

Masa

लेखक के बारे में

Masa

Claude Code workflow और team adoption पर काम करने वाला engineer.