Can I pass an array on the server action? If so, how?
Answered
Jenn posted this in #help-forum
JennOP
I have this
Also, for the
The cart will be used in the statement inside the
cart which is an array. In my Order Page client component, I am submitting the customer data which works well with the server action. The next thing I need is the data of the cart. However, I do not have any idea on how I can pass the array cart on my server action page. Also, for the
cart I need to save it on the table:create table
public.order_items (
order_items_id uuid not null default gen_random_uuid (),
quantity numeric not null,
order_id uuid not null,
water_type_id uuid null,
constraint order_items_pkey primary key (order_items_id),
constraint order_items_order_id_fkey foreign key (order_id) references orders (order_id) on update cascade on delete cascade,
constraint order_items_water_type_id_fkey foreign key (water_type_id) references water_type (id) on update restrict on delete restrict
) tablespace pg_default;The cart will be used in the statement inside the
if (customerId !== undefined) { where I will also save the required data for the order tabletry{
//rest of the data
const {data: customerData, error: customerError} = await supabase.from('customers')
.upsert({
//rest of the data
}).select()
const customerId = customerData?.[0]?.customer_id;
// Check if customerId is defined before using it
if (customerId !== undefined) {
// Proceed with further processing
const water_refilling_station_id = formData.get('water_refilling_station_id')
console.log(water_refilling_station_id, "id of water station")
} else {
// Handle the case when customerId is undefined
return { message: "CustomerId is not available." };
}
}catch(e){
return {message: "Failed to submit the form."}
}Answered by Barbary Lion
When you use bind, it automatically makes you get 2 arguments. I fyou weren't using formState, you'd do it as follow:
On the client component:
On the server component:
On the client component:
<form action={updateCart.bind(null, cart)}>On the server component:
export async function updateCart(cart, formData) {27 Replies
Barbary Lion
You can use the bind method when calling your server action function.
<form action={ serverActionFn.bind(null, cartData) }> (...)
Further explanation on the NextJS documentation:
https://nextjs.org/docs/app/api-reference/functions/server-actions#binding-arguments
I hope that helps! 🙂
<form action={ serverActionFn.bind(null, cartData) }> (...)
Further explanation on the NextJS documentation:
https://nextjs.org/docs/app/api-reference/functions/server-actions#binding-arguments
I hope that helps! 🙂
@Barbary Lion You can use the bind method when calling your server action function.
<form action={ serverActionFn.bind(null, cartData) }> (...)
Further explanation on the NextJS documentation:
https://nextjs.org/docs/app/api-reference/functions/server-actions#binding-arguments
I hope that helps! 🙂
JennOP
I tried this:
ts const [state, formAction] = useFormState(addCustomerOrder, initialState)and then on the formts <form action={formAction.bind(cart)}>`This showed an error on the
addCustomerOrder : No overload matches this call.Overload 1 of 2, '(action: (state: any) => Promise<any>, initialState: any, permalink?: string | undefined): [state: any, dispatch: () => void]', gave the following error.
Argument of type '(prevState: any, formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: any) => Promise<any>'.
Target signature provides too few arguments. Expected 3 or more, but got 1.
Overload 2 of 2, '(action: (state: any, payload: FormData) => Promise<any>, initialState: any, permalink?: string | undefined): [state: any, dispatch: (payload: FormData) => void]', gave the following error.
Argument of type '(prevState: any, formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: any, payload: FormData) => Promise<any>'.
Target signature provides too few arguments. Expected 3 or more, but got 2.on the serveraction:
export default async function addCustomerOrder(prevState: any, formData: FormData, cart: CartItemType[]):Barbary Lion
As you're using useFormState, I think you should try the following:
const [state, formAction] = useFormState(addCustomerOrder.bind(null, cart), initialState);
And when instantiating the form do it as:
<form action={formAction}>
Can you please check if that will work?
const [state, formAction] = useFormState(addCustomerOrder.bind(null, cart), initialState);
And when instantiating the form do it as:
<form action={formAction}>
Can you please check if that will work?
JennOP
This is wat the error shows
No overload matches this call.
Overload 1 of 2, '(action: (state: any) => Promise<any>, initialState: any, permalink?: string | undefined): [state: any, dispatch: () => void]', gave the following error.
Argument of type '(prevState: any, formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: any) => Promise<any>'.
Target signature provides too few arguments. Expected 3 or more, but got 1.
Overload 2 of 2, '(action: (state: any, payload: FormData) => Promise<any>, initialState: any, permalink?: string | undefined): [state: any, dispatch: (payload: FormData) => void]', gave the following error.
Argument of type '(prevState: any, formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: any, payload: FormData) => Promise<any>'.
Target signature provides too few arguments. Expected 3 or more, but got 2.Barbary Lion
I think you've forgotten to set the 'null' parameter inside the bind method
The bind method needs 2 arguments to be passed. The first one should be null in this case.
and the error:
No overload matches this call.
Overload 1 of 2, '(action: (state: FormData) => Promise<FormData>, initialState: FormData, permalink?: string | undefined): [state: FormData, dispatch: () => void]', gave the following error.
Argument of type '(formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: FormData) => Promise<FormData>'.
Target signature provides too few arguments. Expected 2 or more, but got 1.
Overload 2 of 2, '(action: (state: FormData, payload: CartItemType[]) => Promise<FormData>, initialState: FormData, permalink?: string | undefined): [state: ...]', gave the following error.
Argument of type '(formData: FormData, cart: CartItemType[]) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: FormData, payload: CartItemType[]) => Promise<FormData>'.Barbary Lion
Can you show the code for your addCustomerOrder function?
JennOP
export default async function addCustomerOrder(prevState: any, formData: FormData, cart: CartItemType[]): Promise<{ message: string }> {
const cookieStore = cookies()
const supabase = createServerActionClient({ cookies: () => cookieStore })
try{
//rest of the data
const {data: customerData, error: customerError} = await supabase.from('customers')
.upsert({
//data
}).select()
const customerId = customerData?.[0]?.customer_id;
// Check if customerId is defined before using it
if (customerId !== undefined) {
// Proceed with further processing
const water_refilling_station_id = formData.get('refilling_station_id')
console.log(water_refilling_station_id, "id of water station")
const {data: orderData, error: orderError} = await supabase.from('orders')
.upsert({
//rest of the data
}).select()
console.log(orderError, "order data")
const order_id = orderData?.[0]?.order_id;
const {data: orderItems, error: orderItemsError} = await supabase.from('order_items')
.upsert({
quantity: 2,
order_id,
water_type_id : "70e2e497-37b0-4294-a3b3-94bbd95c989a"
})
console.log(orderItemsError, "order items error")
} else {
// Handle the case when customerId is undefined
return { message: "CustomerId is not available." };
}
// revalidatePath('/water_station')
return { message: `Succesfully added the data` }
}catch(e){
return {message: "Failed to submit the form."}
}
}Barbary Lion
Oh, you're expecting 3 arguments and only passing 2.
Barbary Lion
When you use bind, it automatically makes you get 2 arguments. I fyou weren't using formState, you'd do it as follow:
On the client component:
On the server component:
On the client component:
<form action={updateCart.bind(null, cart)}>On the server component:
export async function updateCart(cart, formData) {Answer
Barbary Lion
As you're using formState, you could try expecting only 2 arguments (prevState, and formData) and seeing if that cart one gets injected in the same way as it does when not using formState
JennOP
Thanks, it works now. I even tried with the
prevState and it does retrieve the data of the cartBarbary Lion
Amazing, those are great news!
You should mark this one as answered, so that it may help others!
JennOP
How can I set this as solved?
This is all I see on the tags
@Barbary Lion As you're using formState, you could try expecting only 2 arguments (prevState, and formData) and seeing if that cart one gets injected in the same way as it does when not using formState
JennOP
I just want to ask though, how would this work if you would like to pass on a
message for successful and error ones. From before, const [state, formAction] = useFormState(addCustomerOrder, initialState);, I was using the state.messageBarbary Lion
On the server action, you'd return something like
On the client component, you could use useEffect to watch the state.message and update something (an alert, toast, whatever) upon getting that state update
{status: 'success', message: 'Cart updated'}On the client component, you could use useEffect to watch the state.message and update something (an alert, toast, whatever) upon getting that state update