oRPC
background

Server Actions

Leverage oRPC for type-safe and powerful server actions

Introduction

oRPC makes it simple to implement server actions, offering a robust and type-safe way to manage server-side logic. Server actions are supported out of the box and are powered by several key features:

Requirements

To use a procedure as a server action, the procedure must either:

  1. Be directly callable, or
  2. Use Calling Procedures with Context to create a callable procedure with context.

Usage

"use server"
 
import { ,  } from '@orpc/server'
import {  } from 'zod'
import {  } from 'next/headers'
import {  } from "next/navigation"
import {  } from '@orpc/zod'
 
const  = .(async (, , ) => {
      const  = await ()
      const  = .('Authorization') ? { : 'example' } : 
 
      if(!) {
          throw new ({ : 'UNAUTHORIZED' })
      }
 
      return .({
          : {
              ,
          }
      })
})
 
export const  = 
  .()
  .(
    .({
      : .(),
      : .({
        : .(),
        : .().('image/*').(),
      }),
    }),
  )
  .((, , ) => {
    // ^ context.user is automatically injected
     ('/some-where') // or return some thing
  })

Direct Client Calls

Call server actions directly from client components for greater flexibility:

"use client"
 
import {  } from 'examples/server-action'
import * as React from 'react'
 
export default function () {
  async function () {
    const  = (.('avatar') as HTMLInputElement).
 
    // Call with plain object - types are preserved
    await ({
      : 1992n,
      : {
        : 'Unnoq',
        : ?.[0],
      },
    })
  }
 
  return < ={}>Update User</>
}

With Hooks

import {  } from '@orpc/next/client'
import {  } from 'examples/server-action'
 
// with a hook
const { , , , , , ,  } = ()
 
const  = () => {
  ({ 
    : 1992n,
    : {
      : 'Unnoq',
      : ( .('avatar') as any).files[0],
    },
  })
}

To handle errors gracefully or use hooks for improved reusability, you can leverage createSafeAction and useSafeAction:

import {  } from '@orpc/next/client'
import {  } from '@orpc/next'
import {  } from 'examples/server-action'
 
// on server
const  = ({ 
  : ,
})
 
// with a hook
const { , , , , , ,  } = ()
 
// error will include more information than normal useAction

Enhanced Form Integration

React forms integrate seamlessly with server actions using createFormAction. This setup enables automatic type coercion

// on server
import {  } from '@orpc/next'
import {  } from 'examples/server-action'
const  = ({ 
  : ,
  : () => {
    // redirect('/some-where')
  }
})
 
// on client
import * as React from 'react'
 
export default function () {
  return (
    < ={}>
      {/* Auto convert 1992 to bigint */}
      < ="number" ="id" ="1992" />
      {/* Auto parse user object */}
      < ="text" ="user[name]" ="Unnoq" />
      <
        ="avatar"
        ="file"
        ="user[avatar]"
        ="image/*"
      />
    </>
  )
}

Thanks to Smart Conversion, and Bracket Notation, automatically convert 1992 into a bigint and seamlessly parse objects like user.

Server Actions with Context

Some procedures cannot be used as server actions directly. This is typically because they require additional context, such as user information or other runtime data. In such cases, you can use createProcedureCaller or createSafeAction and createFormAction (built on top of createProcedureCaller) to provide the required context dynamically, making the procedure callable and usable as a server action.

import { ,  } from '@orpc/next'
import { ,  } from '@orpc/server'
import {  } from 'zod'
 
type  = { ?: { : string } }
 
const  = 
.<>()
.(.({ : .() }))
.(({  }) => `Hello, ${}!`)
 
getting({ : 'Unnoq' }) // ❌ cannot call this procedure directly, and cannot be used as a server action
This expression is not callable. Type 'Procedure<Context, undefined, ZodObject<{ name: ZodString; }, "strip", ZodTypeAny, { name: string; }, { name: string; }>, undefined, string> & { ...; }' has no call signatures.
export const = ({ // or createSafeAction or createFormAction : , : async () => { // you can access headers, cookies, etc. here to create context return { : { : 'example' } } }, }) ({ : 'Unnoq' }) // ✅ can call this procedure directly, and can be used as a server action

This flexibility ensures you can adapt server actions to scenarios requiring runtime information, enhancing usability across diverse use cases.

On this page