The React docs state the following:
You can use hidden form fields to provide data to the
<form>
’s action.
The Server Action will be called with the hidden form field data as an
instance of FormData.
…and:
In lieu of using hidden form fields to provide data to the
<form>
’s
action, you can call the bind method to supply it with extra arguments.
Here is the code example they use:
import { updateCart } from './lib.js';
function AddToCart({productId}) {
async function addToCart(formData) {
'use server'
const productId = formData.get('productId')
await updateCart(productId)
}
return (
<form action={addToCart}>
<input type="hidden" name="productId" value={productId} />
<button type="submit">Add to Cart</button>
</form>
)
}
Using the example above, can we not just pass in the productId
using an intermediary async
function (see below)? If not, why not?
Attempt at passing in data via an intermediary function:
import { updateCart } from './lib.js';
function AddToCart({productId}) {
async function addToCart(formData, productId) {
'use server'
await updateCart(productId)
}
async function formAction(formData) {
// ...
await addToCart(formData, productId);
}
return (
<form action={formAction}>
<input type="hidden" name="productId" value={productId} />
<button type="submit">Add to Cart</button>
</form>
)
}
There is an example in the React docs, under <form>
, showing the use of an intermediary async
function, so it should technically work.
I do not understand why they mention hidden form fields and bind
, if an intermediary closure can be used instead.
My initial guess is that a form will not be progressively enhanced (i.e. usable without JS) if the Server Action is not passed in directly. Though I am not sure if that is the only reason.
Relevant docs snippet:
Passing a Server Action to
<form action>
allow users to submit forms
without JavaScript enabled or before the code has loaded.