I have the react client component, it’s a part of a next.js app, this component is a simple form that sends it’s formData to a next.js server action through an async function that will do the following steps:
- Set form button to be disabled & message to “Loading”.
- Send formData to Next.JS via an async server action.
- Set form button to be enabled & message to error if error.
The problem seems to be that react is batching my setState calls, so in execution it’s as if step 1 doesn’t even happen, just step 2 + 3.
I can’t figure out how to circumvent this behaviour.
Here’s the source code:
"use client";
import { SendGiftAction } from "@/app/actions/SendGiftAction";
import { useState } from "react";
export default function GoldGiftForm()
{
let [interactable, SetInteractable] = useState(true);
let [message, setMessage] = useState("");
async function Execute(data: FormData)
{
//These won't change the UI
SetInteractable(false);
setMessage("Loading");
//-------------------------
//Next.JS Server action
let response = await SendGiftAction(data);
//These will change the UI
SetInteractable(true);
setMessage(response.Success ? "" : response.Error);
//------------------------
}
return (
<form action={Execute}>
<h3>Send Gold Gift</h3>
<input
name="userID"
type="text"
placeholder="User ID"
/>
<input
name="gold"
type="number"
placeholder="Gold"
/>
<button type="submit" disabled={!interactable}> Send Gift </button>
<p>{message}</p>
</form>
);
}
This is a code snippet for SendGiftAction: https://pastebin.com/YYQeG0m4
Which is a wrapper that validates data and invokes SendSystemGift:
https://pastebin.com/uD0LLEFL
Both are standard async functions really.
4
You need to understand how async call will excute in your function
//These will run immediately
SetInteractable(false);
setMessage("Loading");
//-------------------------
//This will take time to excute
let response = await SendGiftAction(data);
//So in this time it will excute before api call internall
SetInteractable(true);
setMessage(response.Success ? "" : response.Error);
This is modified code
//These will run immediately
SetInteractable(false);
setMessage("Loading");
//This will take time to excute
let response = await SendGiftAction(data).then((response)=>{SetInteractable(true);
setMessage(response.Success ? "" : response.Error);});
3