React 表单面试中受控组件与非受控组件怎么选?
发布时间:2026/9/11 17:55:34 锦皓数字建站

React 表单面试中受控组件与非受控组件怎么选【免费下载链接】front-end-interview-handbookFront End interview preparation materials for busy engineers (updated for 2026)项目地址: https://gitcode.com/GitHub_Trending/fr/front-end-interview-handbook在 front-end-interview-handbook 的 React 面试手册中表单是反复出现的一类编码题Contact Form、Auth Code Input 等都涉及。动手写表单之前第一个决策就是输入值放在哪里React state受控组件还是原生 DOM非受控组件。这个选择决定了后续写onChange还是写ref也决定了面试官追问实时校验表单重置时你能多快兑现。下面的实现和判断依据全部来自手册中 Forms in React Interviews 与 Signup Form Example 两篇文档。受控与非受控两种写法的完整实现受控组件值存在 React state 中受控组件中React 管理表单元素的状态输入值存储在 state 变量中通过onChange处理程序更新值始终由 React 控制。import { useState } from react; function ControlledForm() { const [name, setName] useState(); function handleChange(event) { setName(event.target.value); } function handleSubmit(event) { event.preventDefault(); alert(Submitted Name: ${name}); } return ( form onSubmit{handleSubmit} label Name: input typetext value{name} onChange{handleChange} / /label button typesubmitSubmit/button /form ); }用户每敲一个字符onChange就用setName(event.target.value)更新 state提交时直接从 state 读取当前值。非受控组件值留在 DOM 中非受控组件中输入值不由 React state 管理而是由 DOM 本身持有。提交时通过两种方式取值FormData从event.target拿到表单元素formData.get(name)的值对应input上的name属性refs用useRef()直接引用input通过nameRef.current.value读取。import { useRef } from react; function UncontrolledForm() { const nameRef useRef(); function handleSubmit(event) { event.preventDefault(); // Access form values using FormData const formData new FormData(event.target); console.log(Name:, formData.get(name)); // Alternatively, access the input via a ref console.log(Name:, nameRef.current.value); } return ( form onSubmit{handleSubmit} label Name: input typetext namename ref{nameRef} / /label button typesubmitSubmit/button /form ); }选择依据对照表与面试中的默认倾向手册给出的两种表单特性对照特性受控表单非受控表单状态存储位置React 状态useState原生 DOM性能更新时需要重新渲染大型表单可能出现问题简单用例下性能更好校验易于实现需要手动校验表单重置容易setState()需要ref.current.value 或触发reset事件用例动态表单、校验、实时更新简单表单、文件上传、集成非 React 代码对应的选择规则需要动态校验、操作或跟踪用户输入例如根据先前回答切换某些字段的可见性或涉及嵌套表单状态时用受控组件处理大型表单、与非 React 代码集成、或以性能为优先时用非受控组件。手册对面试的明确建议面试中的表单通常字段不多两种方式都可行但作者倾向默认选受控组件除非表单极其简单。原因是面试官经常追加 follow-up比如实时校验live validation、条件字段conditional fields、程序化重置programmatic reset——这些用受控 state 实现很直接用 refs 和FormData则要额外搭管道。受控写法的细节checkbox 必须绑checked文本类输入用valueevent.target.value而复选框是布尔值这是文档标注的常见面试失误点checkbox 绑checked而非value读取event.target.checked而非event.target.value。import { useState } from react; function CheckboxExample() { const [isChecked, setIsChecked] useState(false); return ( div input idcheckbox-input typecheckbox checked{isChecked} onChange{(event) setIsChecked(event.target.checked)} / label htmlForcheckbox-inputAgree to terms and conditions/label pCheckbox is {isChecked ? checked : unchecked}/p /div ); }单选组同理用同一个name属性如namegender保证互斥每个选项用checked{gender male}这类比较决定选中态onChange更新为event.target.value。各类受控输入的完整对照来自手册汇总表输入类型关键元素关键值属性状态更新文本输入inputvaluesetState(event.target.value)复选框输入inputcheckedsetState(event.target.checked)单选组inputcheckedsetState(event.target.value)文本区域textareavaluesetState(event.target.value)选择下拉菜单selectvaluesetState(event.target.value)注意textarea与 HTML 不同React 用value属性控制而不是在标签内写文本。文本输入还会考type属性的选用手册给出的对照表type用途内置校验text常规文本输入无number数字文本输入有仅允许数字可配合min/maxemail电子邮件地址有必须包含password安全密码输入无但输入会被掩码search带清除按钮的搜索字段无tel电话号码无可配合patternurlURL有必须以http://或https://开头datetime-local日期和时间选择有color颜色选择器有非受控写法的配套要求非受控表单的值走 DOM因此 Signup Form 文档中的几条 HTML 要求直接决定它能不能工作name属性是表单数据的键没有name的input不会出现在提交数据中formData.get(name)也取不到对应值name与value配对后才会进入 HTTP 请求每个输入配一个label通过htmlForid关联或把input包在label里。placeholder 不是 label——用户输入后会消失屏幕阅读器也可能跳过控件包在form内这样才能获得浏览器的回车提交行为并在onSubmit中拿到包含所有字段数据的event.target。面试追问怎么兑现输入时实时校验受控组件做实时校验最省事把错误信息也放进 state提交或每次输入时检查失败时渲染错误文案。手册示例在其基础上补了文档省略的useStateimportimport { useState } from react; function EmailValidationForm() { const [email, setEmail] useState(); const [error, setError] useState(); const validateEmail (email) { return /^[^\s][^\s]\.[^\s]$/.test(email); }; function handleSubmit(event) { event.preventDefault(); if (!validateEmail(email)) { setError(Please enter a valid email address); return; } setError(); alert(Valid Email: ${email}); } return ( form onSubmit{handleSubmit} label Email: input typeemail value{email} onChange{(event) setEmail(event.target.value)} / /label {error p style{{ color: red }}{error}/p} button typesubmitSubmit/button /form ); }表单重置对照表里的重置行就是两种实现的分叉点受控直接setState()多字段可用useReducer的RESETaction 原子化重置全部字段非受控写ref.current.value 或触发reset事件。这正是默认受控建议的由来重置是高频 follow-up受控下是一行 state 更新非受控下要逐个处理 ref。HTML5 原生校验两种实现都可以叠加required、minLength、pattern等属性由浏览器在提交前校验无需 JavaScript能减少因无效输入引起的重渲染。非受控表单里尤其常用因为浏览器会替你挡掉第一次校验function HTML5ValidationForm() { return ( form label Email: input typeemail required / /label br / label Password (Min 6 characters): input typepassword minLength6 required / /label br / label Phone (Numbers only): input typetel pattern[0-9]{10} required / /label br / button typesubmitSubmit/button /form ); }但手册明确警告客户端校验只是体验层面的便利不是安全边界。攻击者可以完全绕过你的 React 表单直接请求接口任何你在意的约束必填、长度、格式、唯一性都必须服务端重查。手册给出的服务端校验示例是向/api/validate-email发fetch()请求response.ok为假时抛data.message在catch中setError(err.message)并渲染到表单下方。这条服务端必须再校验一次的结论在 Signup Form 文档中同样出现两篇文档口径一致。可选分支允许第三方库时使用 React Hook Form文档说明若题目允许第三方库如 take-home 作业React Hook Form 是手册推荐的补充它用 refs 而非 state 来减少重渲染并内置校验支持。动态字段用useFieldArray处理。Formik 被文档标注为 unmaintained不建议作为面试选型。带校验的注册写法import { useForm } from react-hook-form; function HookFormValidation() { const { register, handleSubmit, formState: { errors }, } useForm(); const onSubmit (data) alert(JSON.stringify(data)); return ( form onSubmit{handleSubmit(onSubmit)} label Email: input typeemail {...register(email, { required: Email is required })} / /label {errors.email p style{{ color: red }}{errors.email.message}/p} label Password: input typepassword {...register(password, { required: Password is required, minLength: { value: 6, message: Password must be at least 6 characters, }, })} / /label {errors.password ( p style{{ color: red }}{errors.password.message}/p )} button typesubmitSubmit/button /form ); }错误信息统一从formState.errors读取并渲染。提交后如何核对结果手册示例自带的核对方式就是提交处理程序里的输出可直接用来验证两条实现路径是否等价受控表单提交后alert(Submitted Name: ${name})弹出 state 中的值文档示例输出值取决于你输入的内容非受控表单console.log会先后打印formData.get(name)和nameRef.current.value两者应一致且等于你输入的值。如果非受控表单里formData.get(name)拿到的是null先检查input是否漏了name属性——没有name的输入项不会进入FormData也不会进入提交数据这是 Signup Form 文档明确指出的行为。继续练习手册在 Forms 章节末尾列出的编码练习题可直接用来验证本文的选择路径Contact Form联系表单、Auth Code Input身份验证代码输入、Generate Table生成表格、Mortgage Calculator抵押贷款计算器、Temperature Converter温度转换器、Flight Booker航班预订器。按字段少、可能需要实时校验的表单题默认走受控只有题目强调大表单性能或文件上传时才考虑非受控。延伸阅读Forms in React Interviews、Signup Form Example in React。【免费下载链接】front-end-interview-handbookFront End interview preparation materials for busy engineers (updated for 2026)项目地址: https://gitcode.com/GitHub_Trending/fr/front-end-interview-handbook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。