Next.js, passing an id to a server action
My goal was to pass an id
to a server action.
Simplest thing is adding that as an hidden input field in the form.
Here’s a todo list example:
'use client'
import { use } from 'react'
import type { Todo } from '@/app/types.ts'
import { deleteTodo } from '@/app/todos/actions/deleteTodo'
export function TodosList({ promise }: { promise: Promise<Todo[]> }) {
const rows = use(promise)
return (
<div>
{rows.map((row) => {
return (
<div key={row.id}>
{row.text}
<form action={deleteTodo}>
<input type='hidden' name='id' value={row.id} />
<button type='submit'>x</button>
</form>
</div>
)
})}
</div>
)
}
In a server action we get the id
value from the FormData object:
'use server'
import { sql } from '@vercel/postgres'
import { revalidatePath } from 'next/cache'
export async function deleteTodo(formData: FormData) {
const id = formData.get('id') as unknown as number
// mutate data
await sql`DELETE FROM todos WHERE id = ${id}`
// revalidate cache
revalidatePath('/todos')
}
An alternative solution is to bind the id to the server action, using bind().
First we modify the server action to accept an id
parameter:
'use server'
import { sql } from '@vercel/postgres'
import { revalidatePath } from 'next/cache'
export async function deleteTodo(id: number) {
// mutate data
await sql`DELETE FROM todos WHERE id = ${id}`
// revalidate cache
revalidatePath('/todos')
}
NOTE: if you also need FormData, append that after that id
parameter in the function parameters:
//...
export async function deleteTodo(id: number, formData: FormData) {
//...
}
Now before using the form action, call bind()
to bind the id
argument to it:
'use client'
import { use } from 'react'
import type { Todo } from '@/app/types.ts'
import { deleteTodo } from '@/app/todos/actions/deleteTodo'
export function TodosList({ promise }: { promise: Promise<Todo[]> }) {
const rows = use(promise)
return (
<div>
{rows.map((row) => {
const deleteTodoWithId = deleteTodo.bind(null, row.id)
return (
<div key={row.id}>
{row.text}
<form action={deleteTodoWithId}>
<button type='submit'>x</button>
</form>
</div>)
}
))}
</div>
)
}
I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter
JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025