Server Actions
Server Actions are asynchronous functions that execute on the server. They can be used in both Server and Client Components to handle form submissions and data mutations in Next.js applications.
Overview
http-react provides a hook for server actions: useAction
Server actions used with this hook should return a data property. Optionally, you can also return status and error for more predictable results. Use the actionData helper function for consistent return values.
Basic Server Action
Define a server action that returns structured data:
'use server'
import { actionData } from 'http-react'
export async function getProfile() {
const profileData = {
email: 'dany@email.com',
name: 'Dany'
}
return actionData(profileData) // Returns { data, error, status }
}Using useAction
Use useAction for things like form submissions. The server action parameter types is automatically inferred.
With FormData
Extract form data using the $form helper:
'use server'
import { actionData, $form } from 'http-react'
import db from './db'
type Entry = {
title: string
description: string
}
export async function createEntry(data: FormData) {
const entry = $form<Entry>(data)
const { title, description } = entry
const newEntry = await db.create({ title, description })
return actionData(newEntry)
}Call the action using submit:
'use client'
import { useAction } from 'http-react'
import { createEntry } from '@/actions'
export default function EntryForm() {
const { submit, isPending } = useAction(createEntry)
return (
<div>
<form action={submit}>
<input
name='title'
type='text'
placeholder='Entry title'
required
disabled={isPending}
/>
<input
name='description'
type='text'
placeholder='Entry description'
required
disabled={isPending}
/>
<button>Save</button>
</form>
{isPending && <p>Creating entry...</p>}
</div>
)
}Auto-Reset Form
Automatically reset the form after submission using formProps:
'use client'
import { useAction } from 'http-react'
import { createEntry } from '@/actions'
export default function EntryForm() {
const { isPending, formProps } = useAction(createEntry, {
onSubmit: 'reset' // Or pass a function that receives the action payload
})
return (
<div>
<form {...formProps}>
<input
name='title'
type='text'
placeholder='Entry title'
required
disabled={isPending}
/>
<input
name='description'
type='text'
placeholder='Entry description'
required
disabled={isPending}
/>
<button>Save</button>
</form>
{isPending && <p>Creating entry...</p>}
</div>
)
}Explicit Parameters
Pass parameters directly instead of using FormData:
'use server'
import { actionData } from 'http-react'
import db from './db'
type Entry = {
title: string
description: string
}
// Single object argument instead of multiple parameters
export async function createEntry({ title, description }: Entry) {
const newEntry = await db.create({ title, description })
return actionData(newEntry)
}Use the params option to provide typed parameters:
'use client'
import { useAction } from 'http-react'
import { createEntry } from '@/actions'
export default function EntryForm() {
const [newEntry, setNewEntry] = useState({
title: '',
description: ''
})
const { isPending, refresh } = useAction(createEntry, {
params: newEntry, // TypeScript validates type compatibility
onResolve() {
// Reset state after success
setNewEntry({
title: '',
description: ''
})
}
})
return (
<div>
<form action={refresh}>
<input
name='title'
type='text'
placeholder='Entry title'
required
disabled={isPending}
value={newEntry.title}
onChange={(e) => {
setNewEntry({
...newEntry,
title: e.target.value
})
}}
/>
<input
name='description'
type='text'
placeholder='Entry description'
required
disabled={isPending}
value={newEntry.description}
onChange={(e) => {
setNewEntry({
...newEntry,
description: e.target.value
})
}}
/>
<button>Save</button>
</form>
{isPending && <p>Creating entry...</p>}
</div>
)
}When using params, the form submission triggers the action with the provided parameters instead of FormData.