Registry / web-framework / next-safe-action

next-safe-action

JSON →
library8.5.2jsnpmunverified

next-safe-action is a library designed for Next.js projects to create type-safe and validated Server Actions. It leverages modern Next.js, React, and TypeScript features to ensure end-to-end type safety from client-side component calls to server-side action execution. The current stable version is 8.5.2, with minor and patch releases occurring frequently to refine types, add features, and improve developer experience. Key differentiators include robust input/output validation, a flexible middleware system for authorization or logging, advanced server error handling, and support for optimistic updates, making it a powerful tool for building reliable and predictable data mutations in Next.js applications.

npm install next-safe-action
INSTALL
IMPORT
SIG · NEXT-SAFE-ACTION
N
next-safe-action
web-frameworkjavascriptv8.5.2
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18226 runs
build_error
glibc
node 18226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

createSafeActionClient
import { createSafeActionClient } from 'next-safe-action';
const { createSafeActionClient } = require('next-safe-action');
next-safe-action is an ESM-first library. Use `import` statements. `createSafeActionClient` is used to initialize the action client with middleware and context.
useAction
import { useAction } from 'next-safe-action/hook';
import { useAction } from 'next-safe-action';
`useAction` is a React hook and must be imported from the `/hook` subpath. It is designed for client components.
safeAction
const action = client.action(schema, async (input) => { /* ... */ });
This is not a direct import but the result of calling `client.action()`. It represents the actual server action function.

This quickstart demonstrates how to define a type-safe server action with input validation using Zod and then execute it from a client component using the `useAction` hook, handling loading states and displaying errors.

import { createSafeActionClient } from 'next-safe-action'; import { z } from 'zod'; import { useAction } from 'next-safe-action/hook'; // server/actions.ts export const actionClient = createSafeActionClient(); export const addTodo = actionClient .schema(z.object({ text: z.string().min(1) })) .action(async ({ text }) => { // Simulate database operation await new Promise(resolve => setTimeout(resolve, 500)); console.log(`Adding todo: ${text}`); return { success: true, newTodo: { id: Date.now(), text } }; }); // app/page.tsx (or any client component) 'use client'; import { useState } from 'react'; import { addTodo } from '@/server/actions'; // Adjust path as needed export default function TodoForm() { const [todoText, setTodoText] = useState(''); const { execute, result, status } = useAction(addTodo, { onSuccess: (data) => { console.log('Todo added successfully:', data?.newTodo); setTodoText(''); }, onError: (error) => { console.error('Failed to add todo:', error); } }); const isLoading = status === 'executing'; return ( <form onSubmit={(e) => { e.preventDefault(); execute({ text: todoText }); }}> <input type="text" value={todoText} onChange={(e) => setTodoText(e.target.value)} placeholder="New todo item" disabled={isLoading} /> <button type="submit" disabled={isLoading}> {isLoading ? 'Adding...' : 'Add Todo'} </button> {result.validationErrors?.text && ( <p style={{ color: 'red' }}>{result.validationErrors.text[0]}</p> )} {result.serverError && ( <p style={{ color: 'red' }}>{result.serverError}</p> )} </form> ); }
Debug
Known issues
breakingnext-safe-action v8 introduced breaking changes, including how action clients are created and used. Refer to the migration guide for a smooth transition.
fix
Consult the official v7 to v8 migration guide at `https://next-safe-action.dev/docs/migrations/v7-to-v8` to update action client initialization and action definitions.
affects: >=8.0.0 <8.5.0
gotchaVersion 8.5.0 narrowed `SafeActionResult` into a discriminated union, meaning `data`, `serverError`, and `validationErrors` are now mutually exclusive in the type system.
fix
Ensure your client-side logic correctly handles the narrowed types. When `result.data` is present, `serverError` and `validationErrors` will be `undefined` (and vice-versa). This improves type safety but might require adjustments to conditional checks.
affects: >=8.5.0
gotchaUsing `require()` for imports will lead to errors as `next-safe-action` is an ESM-first package. Node.js environments configured for CommonJS will not resolve imports correctly.
fix
Always use ES module `import` syntax (e.g., `import { createSafeActionClient } from 'next-safe-action';`). Ensure your Next.js project and `tsconfig.json` are configured for ESM.
affects: >=1.0.0
gotchaWhen using `useAction`, ensure the component where it's called is a React Client Component. Server Actions are defined on the server, but the `useAction` hook must be run in a client environment.
fix
Add the `'use client';` directive at the top of any file defining a component that calls `useAction`.
affects: >=1.0.0
Errors
Common errors & fixes
Error: Cannot find module 'next-safe-action' or its corresponding type declarations.
Incorrect import path or CommonJS project attempting to import an ESM package.
fix
Verify that `next-safe-action` is installed correctly (`npm i next-safe-action`) and ensure you are using ES module imports (`import ... from 'next-safe-action';`). If using CommonJS in Node.js, you might need to configure your project for ESM or use a bundler that handles ESM correctly.
Error: `useAction` is not a function or `useAction` is not defined.
Incorrect import path for the `useAction` hook.
fix
The `useAction` hook must be imported from the `/hook` subpath: `import { useAction } from 'next-safe-action/hook';`.
TypeError: Cannot read properties of undefined (reading 'validationErrors')
Accessing properties like `validationErrors` directly on `result` without checking if `result` or `result.validationErrors` is defined, or if the action even produced validation errors.
fix
Always conditionally access properties of `result` and its nested objects, e.g., `result?.validationErrors?.fieldName` or `if (result.validationErrors) { /* handle errors */ }`. With v8.5.0+, leverage the discriminated union by checking `result.validationErrors` first.
Upgrade
Version history
8.5.2latest on npm
Audit
Dependencies
nextrequiredRequired for Next.js Server Actions functionality.
reactrequiredCore React library for component usage and hooks.
react-domrequiredDOM-specific renderers for React components.
Agent activity
2 hits · last 30 days
node
2
Resources
next-safe-action — npm install next-safe-action · libregistry