Why Use Server Actions?

I can see the benefit of the server component version. Colocated, no need to make an api endpoint in another file.
import { cookies } from 'next/headers'
 
// Server action defined inside a Server Component
export default function AddToCart({ productId }) {
  async function addItem(data) {
    'use server'
 
    const cartId = cookies().get('cartId')?.value
    await saveToDb({ cartId, data })
  }
 
  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}

But isn't the client component version just another way of writing API endpoints?
'use server'
 
export async function addItem(data) {
  const cartId = cookies().get('cartId')?.value
  await saveToDb({ cartId, data })
}

Guess you can use it in form without javascript:
'use client'
 
import { addItem } from './actions.js'
 
// Server Action being called inside a Client Component
export default function AddToCart({ productId }) {
  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}

But using it this way feels sucky as there is no way (that I know of) to make it typesafe.
Was this page helpful?