Issue: Data Not Updating Properly in Next.js Server Actions
upangka opened this issue · 1 comments
Verify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Home China
Available memory (MB): 40768
Available CPU cores: 12
Binaries:
Node: 20.13.1
npm: 10.5.2
Yarn: 1.22.22
pnpm: 9.10.0
Relevant Packages:
next: 15.0.3 // There is a newer version (15.1.0) available, upgrade recommended!
eslint-config-next: N/A
react: 18.3.1
react-dom: 18.3.1
typescript: 5.7.2
Next.js Config:
output: N/A
⚠ There is a newer version (15.1.0) available, upgrade recommended!
Please try the latest canary version (`npm install next@canary`) to confirm the issue still exists before creating a new issue.
Read more - https://nextjs.org/docs/messages/opening-an-issue
Which example does this report relate to?
server action
What browser are you using? (if relevant)
Chrome 131.0.6778.109
How are you deploying your application? (if relevant)
next dev
Describe the Bug
I am working on a Next.js project with the following file structure:
app
│ page.tsx
├─actions
│ index.ts
├─api
│ route.ts
└─home
data.ts
edit-form.tsx
page.tsx
Code Overview
You can view the project source code here: https://vscode.dev/github/hzz4j/nextjs-research.
home/page.tsx
This page retrieves a number from the server and passes it to the form:
import EditForm from './edit-form'
import { get } from './data'
export default async function Page() {
const num = await get()
return (
<section className="mx-auto w-fit">
<EditForm num={num} />
</section>
)
}
home/edit-form.tsx
This component renders a form that allows the user to update the number.
'use client'
import { useActionState } from 'react'
import { updateNum } from '../actions'
type State = {
msg: string
}
export default function EditForm({ num }: { num: number }) {
const initialState: State = { msg: 'success' }
const updateNumByIndex = updateNum.bind(this, 0)
const [state, formAction] = useActionState(updateNumByIndex, initialState)
return (
<form action={formAction}>
<input type="number" name="amount" defaultValue={num} className="border p-2" />
<p>Message: {state.msg}</p>
<button className="rounded-md bg-green-500 p-2 text-white">Update</button>
</form>
)
}
home/data.ts
This module handles fetching and updating the number. The data is stored in a nums array.
'use server'
const nums = [1]
export async function get() {
console.log('Fetching:', nums)
return nums[0]
}
export async function update(index: number, value: number) {
nums[index] = value
console.log('Updated:', nums)
}
actions/index.ts
This server action updates the number and revalidates the page.
'use server'
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'
import { update } from '../home/data'
type State = {
msg: string
}
export async function updateNum(index: number, _: State, formData: FormData) {
await update(index, +formData.get('amount'))
revalidatePath('/')
redirect('/')
return { msg: 'success' }
}
app/page.tsx
This is the main page, which also fetches the number:
import { get } from './home/data'
export default async function App() {
const num = await get()
return (
<section className="container mx-auto text-3xl font-bold">{num}</section>
)
}
api/route.ts
This API endpoint allows updating the number via query parameters.
import { NextRequest } from 'next/server'
import { update } from '../home/data'
export async function GET(request: NextRequest) {
const v = request.nextUrl.searchParams.get('v')
if (v) {
await update(0, +v)
return new Response('success')
}
return new Response('error')
}
Problem Description
- When I update the number using the form in
edit-form.tsx
, e.g., changing it to 10, the page redirects back to/
, but the updated value is not reflected. The nums array does not appear to be updated.
- However, when I update the number using the API endpoint (http://localhost:3000/api?v=10), the value updates successfully, and the updated value is displayed when I visit (http://localhost:3000).
Question
Why does updating the value via the form not work, while updating it via the API endpoint works as expected? How can I ensure that the form updates the data properly and reflects the updated value on the page after redirection?
Additional Notes
- I am using the use server directive for both
actions/index.ts
andhome/data.ts
. - The nums array is defined as a server-side constant in
data.ts
. - I do not want to use MySQL, Redis, or any other third-party storage solutions to store the data. I just want to understand why the Server Action is not updating the data successfully.
Any insights or suggestions would be greatly appreciated!
Expected Behavior
My expectation is that after clicking the update button in edit-form, the data will be successfully updated via Server Actions and the updated data will be displayed on the homepage /.
To Reproduce
actions/index.ts
This server action updates the number and revalidates the page.
'use server'
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'
import { update } from '../home/data'
type State = {
msg: string
}
export async function updateNum(index: number, _: State, formData: FormData) {
await update(index, +formData.get('amount'))
revalidatePath('/')
redirect('/')
return { msg: 'success' }
}
When I update the number using the form in edit-form.tsx
, e.g., changing it to 10, the page redirects back to /
, but the updated value is not reflected. The nums array does not appear to be updated. Here is the demo link