Note: the imported Chinese source file available locally was truncated mid-article. This English version is reconstructed from the available source content and the original topic.
When building with Next.js, a common question comes up quickly:
Should form data be submitted from the client with fetch, or should it go through a Next.js Server Action?
This article breaks down:
- how client-side
fetchsubmissions work - how Server Actions work
- the advantages and disadvantages of each
- when to choose one over the other
1. What is a client-side fetch submission?
A client-side fetch submission means you send data directly from a React client component to an API endpoint, such as a Next.js route handler, Strapi, or another backend service.
Example:
'use client'
export default function Home() {
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
const formData = new FormData(e.currentTarget)
await fetch('http://localhost:1337/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: formData.get('name'),
email: formData.get('email'),
}),
})
}
return (
<form onSubmit={handleSubmit}>
<input name="name" />
<input name="email" />
<button type="submit">Submit</button>
</form>
)
}
Advantages
- easy to understand if you already know REST-style API calls
- works well with third-party backends
- gives the client full control over loading states and interaction flow
Drawbacks
- the API endpoint is exposed directly to the client
- you often need to handle validation, auth, and error management in more places
- more boilerplate for forms that only need server-side processing
2. What is a Server Action submission?
A Server Action lets you submit form data directly to a function that runs on the server, without wiring your own client-side fetch call for the basic flow.
Example:
export default function Page() {
async function createUser(formData: FormData) {
'use server'
const name = formData.get('name')
const email = formData.get('email')
// Save to database or call another backend here
console.log({ name, email })
}
return (
<form action={createUser}>
<input name="name" />
<input name="email" />
<button type="submit">Submit</button>
</form>
)
}
Advantages
- simpler form wiring in many cases
- logic stays on the server by default
- easier to keep secrets, tokens, and internal service calls out of the browser
- integrates naturally with the App Router data flow
Drawbacks
- more tightly coupled to Next.js conventions
- less familiar if your team already uses explicit REST or GraphQL patterns everywhere
- some interaction-heavy flows still feel more natural with client-side requests
3. Core difference
The main distinction is where the submission logic lives.
| Approach | Where the submission starts | Where the main logic runs | API surface exposed to the browser |
|---|---|---|---|
Client-side fetch |
Browser | Backend endpoint | Usually explicit |
| Server Action | Form posts into Next.js server code | Next.js server | Usually less direct |
In other words:
fetchis closer to the classic frontend-calls-backend model- Server Actions are closer to server-first form handling built into Next.js
4. When should you use fetch?
Client-side fetch is usually the better fit when:
- you are talking to an external API directly
- the UI needs fine-grained client interaction and optimistic updates
- your app already follows a clear API-layer architecture
- you want the frontend and backend to stay more decoupled
5. When should you use Server Actions?
Server Actions are usually the better fit when:
- you are building with the Next.js App Router
- the form is straightforward and server-centric
- you want to avoid exposing internal implementation details to the client
- you want less boilerplate for form submission and validation flow
6. Recommended practical rule
If the form is mostly a standard create, update, or delete action handled inside your Next.js app, Server Actions are often the cleaner default.
If the frontend needs to call a public API directly, or your architecture already depends heavily on explicit API contracts, client-side fetch remains a strong choice.
The right answer is not that one is always better. It depends on whether your app is more server-first or API-first.
Summary
- Use client-side
fetchwhen you need explicit API calls and strong client control. - Use Server Actions when you want a more integrated server-side form flow inside Next.js.
- Think about security boundaries, architecture, and the complexity of the interaction before choosing.
For many App Router projects, Server Actions make the default path simpler. But for API-heavy or highly interactive apps, fetch is still the more flexible tool.
