You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js表单开发:是否该用useState?两段代码差异及选型

在Next.js中使用表单:useState管理输入值 vs 直接获取DOM值

先看你提供的两段代码:

非受控组件写法(不使用useState)

'use client';

export default function Page() {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    console.log(e.currentTarget.email.value);
    console.log(e.currentTarget.password.value);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="email" />
      <input type="password" name="password" />
      <button type="submit">login</button>
    </form>
  );
}

受控组件写法(使用useState)

'use client';

import { useState } from 'react';

export default function Page() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    console.log(email);
    console.log(password);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        name="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <input
        type="password"
        name="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="submit">login</button>
    </form>
  );
}

两种写法的核心差异

  • 数据存储方式:
    非受控组件的输入值存在DOM元素本身,只有提交时才通过e.currentTarget读取;受控组件的输入值存在React状态(useState)里,输入时实时更新状态,提交时直接用状态值。
  • 实时交互能力:
    受控组件能实时响应输入变化——比如输入时做格式校验(如邮箱格式检查)、禁用不符合要求的提交按钮、实时显示输入提示等;非受控组件做不到这些,只能在提交时一次性处理。
  • 代码可维护性:
    简单场景下非受控组件更简洁,但表单字段变多(比如添加用户名、手机号)或需要状态联动(如某个输入变化影响其他字段)时,受控组件的集中状态管理会更清晰,也更容易和React生态工具(如Formik、React Hook Form)集成。
  • 符合React理念程度:
    React是声明式框架,受控组件通过状态驱动UI,符合其设计思想;非受控组件依赖DOM操作,属于命令式写法,和React的声明式理念有冲突。

哪种写法更规范正确?

没有绝对的标准答案,取决于你的业务场景:

  • 如果是极简表单(仅收集数据提交,无任何实时交互需求):两种写法都可行,非受控组件代码更短,上手更快。
  • 如果是需要复杂交互的表单(实时验证、输入限制、多字段联动、状态共享):必须用受控组件,这是React官方推荐的方式,代码更可预测、易维护,也更贴合Next.js的客户端组件开发模式。
  • 极端性能场景(比如表单有几十上百个字段):受控组件的频繁重渲染可能带来微小性能损耗,这时可以考虑非受控组件配合useRef读取DOM值,但这种情况非常少见,大部分业务场景受控组件的性能完全够用。

另外在Next.js中,两种写法都能在客户端组件中正常运行,但受控组件更方便和Server Actions结合——你可以直接把状态值作为参数传给Server Action函数,无需额外读取DOM。

内容的提问来源于stack exchange,提问作者pvp11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:17