I am trying to use the new useActionState from React 19 in my Next js project using a form.
I managed to import it by installing the latest releases :
//package.json
"next": "v15.0.0-canary.134",
"react": "19.0.0-rc-a19a8ab4-20240829",
"react-dom": "19.0.0-rc-a19a8ab4-20240829",
So first i created a server action as below :
const { WalletModel } = require("../../models");
import { auth } from "@/auth";
import connectDB from "../../db.connect";
//------------------------------------------------------------------------------
interface IActionState {
success: string | null;
error: string | null;
}
const createWallet = async (
previousState: IActionState,
formData: FormData
): Promise<IActionState> => {
try {
const session = await auth();
await connectDB();
const title = formData.get("title") as string;
const user = session?.user?.email as string;
const wallet = new WalletModel({ title, user });
await wallet.save();
console.log("Wallet created successfully");
return { success: `Wallet ${title} created successfully`, error: null };
} catch (error: any) {
return { success: null, error: error.message };
}
};
export default createWallet;
and trying to consume it in a client form :
"use client";
import { useActionState } from "react";
import { useRouter } from "next/navigation";
import TextField from "@mui/material/TextField";
import createWallet from "./WalletForm.server";
import LoadingButton from "@mui/lab/LoadingButton";
import { Button } from "@mui/material";
import { IActionState } from "./WalletForm.server";
//---------------------------------------------------------
const WalletForm = () => {
const [state, action, isPending] = useActionState(createWallet, {
success: null,
error: null,
} as IActionState);
console.log("state", state);
console.log("isPending", isPending);
const router = useRouter();
return (
<form
action={action}
//onSubmit={handleSubmit}
className="space-y-6"
>
<div>
<TextField
name="title"
variant="filled"
fullWidth
required
label="Title"
sx={{
background: "white",
}}
/>
</div>
...rest is irrelevant
so the problem is that while i get the initial state as defined in the client comp, it turns to undefined when the server action returns its data so console.log(state)
always returns undefined, isPending
variable works fine
any ideas why ?
For anyone having the same issue, in my case was headers sent from middleware.ts
where i replaced :
const response = NextResponse.next({
headers: requestHeaders,
});
with :
const response = NextResponse.next({
request: {
headers: requestHeaders,
},
});
As per issue : https://github.com/vercel/next.js/issues/50659
And comment : https://github.com/vercel/next.js/issues/50659#issuecomment-2211256368
It seems that intercepting headers was messing up the server action response, now its ok.
1