我使用 Next13.5、应用程序路由器制作了如下联系表。
但是try-catch中的setIsLoading效果不佳。它在服务器操作响应返回的同时触发。
服务器操作是简单的电子邮件发送,代码中是 sendEmail() 。
有谁知道表单操作会发生什么? 我想知道的是为什么状态更新时间会延迟。 sendEmail() 始终有效。
"use client"
import { sendEmail } from '@/features/sendEmail'
export const Contact() => {
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState('')
const formAction = async () => {
try {
setIsLoading(true) // this fire at the same as end of sendEmail()
const result = await sendEmail(formData) // this function is server action
result.success ? router.push("thanks") : setError("server error")
} catch (error) {
setServerError(`${error}`)
setIsLoading(false)
}
}
return (
<form action={formAction}>
{/* some inputs */}
<button type="submit" disabled={isLoading}>
{isLoading ? 'sending' : 'send'}
</button>
</form>
)
}
// ref: https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations
我尝试将其重写为 onClick 函数,如下所示,在提交按钮处,效果很好。
isLoading 在按下按钮时更新为 true,并在发送电子邮件后恢复为 false。
const submitFunc async () => {
setIsLoading(true)
const result = await sendEmail(formData) // this function is server action
setIsLoading(false)
}
我找到了解决方案。我使用 useFormStatus() 并且加载效果很好。 我希望它对任何人都有帮助!
'use client'
import { useFormStatus } from 'react-dom'
export function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" aria-disabled={pending}>
Add
</button>
)
}
该组件需要嵌套在表单中。只有这样才有效。
将来,您将能够在外部使用
useActionState
(取代 useFormState)。请参阅https://github.com/facebook/react/pull/28491