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

Next.js中不使用JQuery和document.getElementById如何单按钮提交两个表单

现有代码的问题

  • 触发Next.js SSR/SSG阶段的DOM访问错误:Next.js在服务端渲染/静态生成阶段不存在浏览器端的document对象,直接调用document.getElementById会在服务端执行时抛出未定义错误。
  • 违反React Hook使用规则:useEffect属于React Hook,只能在组件顶层或自定义Hook中调用,不能嵌套在普通函数submitForms内部,运行时会直接抛出Hook规则错误。
  • 触发时机完全错误:useEffect的回调会在组件渲染完成后自动执行,你把提交逻辑放在这里完全不符合「点击按钮触发提交」的需求。
  • 不符合React最佳实践:直接操作DOM获取表单元素不是React的推荐写法,应该使用useRef获取DOM引用。

正确实现方式

方案1:基于useRef绑定原生表单(无需操作document)

适合需要使用原生表单action提交的场景,Next.js 13+ App Router需要加'use client'标记客户端组件,Pages Router可直接省略该标记:

'use client';
import { useRef } from 'react';

export default function FormPage() {
  // 给两个表单分别创建ref引用
  const form1Ref = useRef<HTMLFormElement>(null);
  const form2Ref = useRef<HTMLFormElement>(null);

  const handleSubmitAll = () => {
    // 校验ref存在后依次提交两个表单
    form1Ref.current?.submit();
    form2Ref.current?.submit();
  };

  return (
    <div>
      {/* 第一个表单绑定ref */}
      <form ref={form1Ref} action="/api/submit1" method="POST">
        <input name="field1" />
      </form>

      {/* 第二个表单绑定ref */}
      <form ref={form2Ref} action="/api/submit2" method="POST">
        <input name="field2" />
      </form>

      {/* 单个按钮触发双表单提交 */}
      <button type="button" onClick={handleSubmitAll}>
        提交所有表单
      </button>
    </div>
  );
}

方案2:受控组件直接提交状态(无DOM操作,更推荐)

如果你的两个表单已经是受控组件,数据存储在组件state中,可直接在点击事件中批量提交数据,完全不需要操作表单DOM:

'use client';
import { useState } from 'react';

export default function FormPage() {
  // 两个表单的状态数据
  const [form1Data, setForm1Data] = useState({ field1: '' });
  const [form2Data, setForm2Data] = useState({ field2: '' });

  const handleSubmitAll = async () => {
    // 同时提交两份表单数据
    await Promise.all([
      fetch('/api/submit1', { 
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(form1Data) 
      }),
      fetch('/api/submit2', { 
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(form2Data) 
      })
    ]);
    // 提交成功后可加跳转、提示等后续逻辑
  };

  return (
    <div>
      <form>
        <input 
          name="field1" 
          value={form1Data.field1} 
          onChange={e => setForm1Data({...form1Data, field1: e.target.value})} 
        />
      </form>
      <form>
        <input 
          name="field2" 
          value={form2Data.field2} 
          onChange={e => setForm2Data({...form2Data, field2: e.target.value})} 
        />
      </form>
      <button type="button" onClick={handleSubmitAll}>提交所有表单</button>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 20:45:04