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
相关产品推荐
相关产品推荐

