在NextJs@13中,setState在表单操作中不起作用

问题描述 投票:0回答:2

我使用 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)
}

reactjs forms next.js app-router
2个回答
0
投票

我找到了解决方案。我使用 useFormStatus() 并且加载效果很好。 我希望它对任何人都有帮助!

文档:https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations#displaying-loading-state


0
投票
'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

© www.soinside.com 2019 - 2024. All rights reserved.