Prompt

build a form in react

Technology · Developer Tools / Developer tools3 observationsLast seen Jul 23, 2026

Latest observation

Jul 23, 2026 · GeminiWeb search: on

Building a form in React depends on your use case. Below are two standard approaches: a vanilla React version using controlled state (best for simple forms) and an industry-standard production setup using React Hook Form + Zod (best for scalable, performant validation). Method 1: Vanilla React (Controlled Form)This approach uses standard useState hooks to manage input data. It is ideal for small forms where you don't want external dependencies. JavaScriptimport { useState } from 'react';

export default function BasicForm() {

const [formData, setFormData] = useState({

  • name: '',
  • email: '',
  • role: 'developer',

});

const [errors, setErrors] = useState({});

const [submitted, setSubmitted] = useState(false);

// Validate fields on submission

const validate = () => {

const newErrors = {};

if (!formData.name.trim()) newErrors.name = 'Name is required';

if (!formData.email.trim()) {

newErrors.email = 'Email is required';

} else if (!/\S+@\S+.\S+/.test(formData.email)) {

newErrors.email = 'Invalid email address';

}

return newErrors;

};

const handleChange = (e) => {

const { name, value } = e.target;

  • setFormData((prev) => ({ ...prev, [name]: value }));

};

const handleSubmit = (e) => {

e.preventDefault(); // Prevent full page reload

const validationErrors = validate();

if (Object.keys(validationErrors).length > 0) {

setErrors(validationErrors);

setSubmitted(false);

} else {

setErrors({});

setSubmitted(true);

console.log('Form Submitted Successfully:', formData);

}

};

return (

  • <div style={{ maxWidth: '400px', margin: '2rem auto', fontFamily: 'sans-serif' }}>

<h2>Contact Us</h2>

  • {submitted && <p style={{ color: 'green' }}>Form submitted successfully!</p>}

<form onSubmit={handleSubmit} noValidate>

{/* Name Field */}

  • <div style={{ marginBottom: '1rem' }}>
  • <label htmlFor="name" style={{ display: 'block', marginBottom: '.5rem' }}>Name</label>

<input

id="name"

type="text"

name="name"

value={formData.name}

onChange={handleChange}

  • style={{ width: '100%', padding: '0.5rem' }}

/>

  • {errors.name && <span style={{ color: 'red', fontSize: '0.85rem' }}>{errors.name}</span>}

</div>

{/* Email Field */}

  • <div style={{ marginBottom: '1rem' }}>
  • <label htmlFor="email" style={{ display: 'block', marginBottom: '.5rem' }}>Email</label>

<input

id="email"

type="email"

name="email"

value={formData.email}

onChange={handleChange}

  • style={{ width: '100%', padding: '0.5rem' }}

/>

  • {errors.email && <span style={{ color: 'red', fontSize: '0.85rem' }}>{errors.email}</span>}

</div>

{/* Role Select Dropdown */}

  • <div style={{ marginBottom: '1rem' }}>
  • <label htmlFor="role" style={{ display: 'block', marginBottom: '.5rem' }}>Role</label>

<select

id="role"

name="role"

value={formData.role}

onChange={handleChange}

  • style={{ width: '100%', padding: '0.5rem' }}

>

<option value="developer">Developer</option>

<option value="designer">Designer</option>

<option value="manager">Manager</option>

</select>

</div>

  • <button type="submit" style={{ padding: '0.5rem 1rem', cursor: 'pointer' }}>

Submit

</button>

</form>

</div>

);

}

  • Method 2: Enterprise Ready (React Hook Form + Zod)For larger forms, managing state per keystroke can cause unnecessary re-renders. Modern React applications typically combine React Hook Form with Zod schema validation. 1. InstallationBashnpm install react-hook-form zod @hookform/resolvers

2. Form ComponentTypeScriptimport React from 'react';

import { useForm } from 'react-hook-form';

import { zodResolver } from '@hookform/resolvers/zod';

import { z } from 'zod';

// Define schema with validation rules

const formSchema = z.object({

  • username: z.string().min(3, 'Username must be at least 3 characters'),
  • email: z.string().email('Please enter a valid email address'),
  • password: z.string().min(8, 'Password must be at least 8 characters'),

});

type FormData = z.infer<typeof formSchema>;

export default function ZodForm() {

const {

register,

handleSubmit,

  • formState: { errors, isSubmitting },

} = useForm<FormData>({

  • resolver: zodResolver(formSchema),

});

  • const onSubmit = async (data: FormData) => {

// Simulate API call

await new Promise((resolve) => setTimeout(resolve, 1000));

console.log('Valid Form Data:', data);

};

return (

<form onSubmit={handleSubmit(onSubmit)} style={{ maxWidth: '400px', margin: '2rem auto' }}>

<div>

<label>Username</label>

<input {...register('username')} />

  • {errors.username && <p style={{ color: 'red' }}>{errors.username.message}</p>}

</div>

<div>

<label>Email</label>

<input type="email" {...register('email')} />

  • {errors.email && <p style={{ color: 'red' }}>{errors.email.message}</p>}

</div>

<div>

<label>Password</label>

<input type="password" {...register('password')} />

  • {errors.password && <p style={{ color: 'red' }}>{errors.password.message}</p>}

</div>

<button type="submit" disabled={isSubmitting}>

  • {isSubmitting ? 'Submitting...' : 'Submit'}

</button>

</form>

);

}

  • Best Practices to FollowPrevent Default Reload: Always call e.preventDefault() inside submit handlers when using standard forms to prevent full browser reloads.Label Association: Bind inputs using htmlFor="id" on <label> elements and matching id="id" on inputs for accessibility.Disable Submission State: Disable the submit button during API requests (isSubmitting) to prevent duplicate payloads.Controlled vs. Uncontrolled: Use useState when input values drive other UI components in real-time. Use react-hook-form (uncontrolled under the hood) when optimizing performance for complex forms.

Observation history

See 2 earlier observations

Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (3 observations for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.