Reputation: 41
I made a contact form like below with Next13.5, app router.
But setIsLoading in the try-catch doesn’t work well. It fires at the same time as the server action response returns.
The server action is simple email sending and it is sendEmail() at the code.
Does anyone know what happens at the form action? What I want to know is why the state update timing is delayed. sendEmail() is always working.
"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
I tried to rewrite it to onClick function like below at the submit button and that worked well.
isLoading was updated to true at the time the button was pressed, and it reverted to false after the email was sent.
const submitFunc async () => {
setIsLoading(true)
const result = await sendEmail(formData) // this function is server action
setIsLoading(false)
}
Upvotes: 4
Views: 1243
Reputation: 15908
'use client'
import { useFormStatus } from 'react-dom'
export function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" aria-disabled={pending}>
Add
</button>
)
}
This component needs to be nested in the form. Only this way it works.
In the future, you will be able to use useActionState
outside (which replaces useFormState). See https://github.com/facebook/react/pull/28491
Upvotes: 1
Reputation: 41
I got a solution. I use useFormStatus() and loading works well. I hope it helps anyone!
Upvotes: 0