[React 19] Incorrect infered response type in server actions with React 19
alexanderalmstrom opened this issue · 0 comments
Summary
Server actions in Next.js return Promise<void>
instead of the infered response type.
This is most likely a issue in react 19 or @types/react 19 since it works as exepected with both Next.js 14 and Next.js 15 and can only be reproduced when upgrading from React 18 to 19.
Example action:
https://github.com/alexanderalmstrom/next-15-server-actions/blob/main/src/app/actions.ts
main
branch with React 19:
https://github.com/alexanderalmstrom/next-15-server-actions/tree/main
react-18
branch with React 18.3.1 where the response is infered correctly with Promise<{ message: string }>
https://github.com/alexanderalmstrom/next-15-server-actions/tree/react-18
Both branches uses the same Next version 15.1.0 and the same server action.
I'm aware of the useActionState
(previously called useFormState
)...
"use client";
import { type ComponentProps, useActionState } from "react";
import { exampleFormActionState } from "../actions";
export default function FormWithActionState(props: ComponentProps<"form">) {
const [state, action] = useActionState(exampleFormActionState, {
message: "",
});
return (
<form action={action} {...props}>
<input type="text" name="name" />
<button type="submit">Submit</button>
{state.message && <p>{state.message}</p>}
</form>
);
}
but is it expected that the action should return Promise<void>
?
and we have to type the state like this, instead of having the types infered automatically for us in typescript?
type FormState = {
message: string;
};
export async function exampleFormActionState(
prevState: FormState,
formData: FormData
) {
const name = formData.get("name");
if (!name || typeof name !== "string") {
return { message: "VALIDATION_ERROR" };
}
return { message: `Hello, ${name}!` };
}
The thing is, what if I don't want to use useActionState
? Lets say that we pass the action as prop to the form element, and then use auseFormStatus
and a pending state for the button. Then that's not possible because of this error.