Playwright, `useActionState`, and bound server functions
Quick one that has a fix but no explanation for why the problem is there (yet).
I have a server action:
'use server';
export async function serverAction(param1) {
const newState = doThings(param1);
return newState;
}
I also have form that uses useActionState
to handle the form submission:
const boundServerAction = serverAction.bind(
null,
param1
);
const [state, formAction] = useActionState(boundServerAction, null);
return (
<form action={formAction}>
<button type="submit">Submit</button>
</form>
);
This works in the browser, but in Playwright state
is never updated. An unbound function works fine.
This makes it seem as though it's to do with the param binding, possibly because prevState: unknown, formData: FormData
are added to the server action params. But in this case they're not used, so should it matter? What is Playwright doing in instrumentation that stops this from working? I'm not sure and haven't had time to investigate.
But there are two workarounds here:
Options 1. Wrap the server action
Simplest solution: Just don't bind the server action.
const [state, formAction] = useActionState(() => serverAction(param1), null);
return (
<form action={formAction}>
<button type="submit">Submit</button>
</form>
);
Option 2. Use form inputs
To be clear, I don't like this. I shouldn't need to expose param1
. But this works and may suit your use case for some reason.
Update the server action to use formData
:
'use server';
export async function serverAction(prevState, formData) {
const newState = doThings(formData.get('param1'));
return newState;
}
Update your form to add param1
as a hidden value.
const [state, formAction] = useActionState(serverAction, null);
return (
<form action={formAction}>
<input type="hidden" name="param1" value={param1} />
<button type="submit">Submit</button>
</form>
);