我无法将数据保存到数据库,然后有条件地在 React 中渲染组件。
我想显示一个消息框,将消息保存到数据库,然后删除消息框并显示一条
thank you
消息。
对于上下文来说,这是
next.js
框架中的 React 代码。
用户导航至联系页面
contact/index.js
。默认功能是
import { useState } from 'react';
import style from '@/styles/general.module.css';
export default function MessageFlow () {
const [isSubmitted, setSubmitted] = useState(false);
return (
<>
{
isSubmitted ? (
<p className={style.centerText}>Thank you. We will be in touch.</p>
) : (
<>
<Messageform
isSubmitted={false}
onShow={() => setSubmitted(true)}
/>
</>
)
}
</>
);
}
在上面的同一个文件中,
<Messageflow />
是<Messageform />
,即
function Messageform({ onShow }) {
return (
<>
<h1 className={style.centerText}>
Contact
</h1>
<form onSubmit={handleSubmit}>
<textarea type="text" id="messageText" className={style.messageBox} placeholder=" General feedback"/>
<br></br>
<button type="submit" onClick={onShow} className={style.greenButtonCont}>Submit</button>
</form>
</>
)
}
上面这是
handleSubmit
as
const handleSubmit = async (note) => {
note.preventDefault();
const data = {
noteData: note.target.messageText.value
}
const JSONdata = JSON.stringify(data)
const endpoint = '/api/messageForm'
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSONdata,
}
await fetch(endpoint, options);
}
所以问题是:按照所写的代码,消息框消失并出现
Thank you. We will be..
,但消息未保存到数据库中。错误 Form submission canceled because the form is not connected contact:1
显示在浏览器开发工具中。
关于 S.O. 的一个答案这里谈到了操作DOM,但是React明确表示不要碰DOM。另外,这只是简单的表单提交,所以我认为您不需要为此触及 DOM。
另一个答案here讨论了如何在有
onClick
的按钮上不应该有 type="submit"
处理程序。
我do在我的按钮上有一个
onClick
处理程序,其中有submit
,因为这是我将isSubmitted
状态更新为true
的地方。更新 isSubmitted
会导致消息框消失并出现 Thank you
消息。
我尝试在
isSubmitted
内更新handleSubmit
,但这就是事情变得复杂的地方。
如果我只是像
isSubmitted
一样传入 <form onSubmit={handleSubmit(isSubmitted)}>
并将 setSubmitted(true)
放在 const handleSubmit = async (note) => ..
函数中,那么我会收到运行时错误
TypeError: note.preventDefault is not a function
我认为这是因为
isSubmitted
不是事件对象,所以你不能对其执行 note.preventDefault 。
我还尝试解构
<form ..
部分和 const handleSubmit = async
部分中的参数,并使用不同的组合,例如
<form onSubmit={handleSubmit({ isSubmitted })>
...
const handleSubmit = async ({isSubmitted})
但是结果
ReferenceError: note is not defined
。
<form onSubmit={handleSubmit({ isSubmitted })>
...
const handleSubmit = async ({note, isSubmitted})
结果
TypeError: note.preventDefault is not a function
。
尝试虚拟变量
<form onSubmit={handleSubmit({ _a, isSubmitted })>
...
const handleSubmit = async ({note, isSubmitted})
结果
ReferenceError: _a is not defined
。
当我从
onClick={onShow}
中删除 <button type="submit"..
时,消息 确实 保存到我的数据库中;但消息框停留在那里,并且没有出现 thank you
消息。
我尝试将所有内容移至
onClick
,但读到您不应该使用按钮onClick
功能来提交表单数据,因为这样您就无法响应提交事件。当我尝试将 isSubmitted
传递给 handleSubmit
时,我认为这是一个类似的问题。它使 note
不再是一个事件。
那么如何保存消息、更新状态、删除消息框,然后显示
thank you
消息呢?似乎我需要 handleSubmit
和 onSubmit
,但两者一起导致了问题。
如果您想将任何参数传递给 eventHandler 函数,就像您的情况一样,这是第一个问题
<form onSubmit={handleSubmit(isSubmitted)}>
您应该只给出一个函数名称(只需提供不带括号的handleSubmit),然后在提交表单时事件对象将传递给该函数。这就是为什么在 handleSubmit 函数表达式中您接受此参数作为注释。或者,如果您想传递自己的参数,您需要执行以下操作<form onSubmit={() => handleSubmit(note, isSubmitted)}>
在这里,您传递了一个箭头函数,但没有立即调用它。然后您可以使用在handleSubmit函数中传递的任何参数。
第二个问题,你是对的,你不需要按钮上的单击处理程序来更新状态。仅在消息保存到数据库后才应该更新状态。如果我理解正确的话你可以尝试:
<form onSubmit={() => handleSubmit(note, onShow)}>
将onShow函数传递给handleSubmitconst handleSubmit = async (note, onShow) => {
//saving to db here
onShow();
//calling onShow will set Submitted to true;
}