Skip to content

Commit dbfb6c4

Browse files
authored
[test] Add failing test for useActionState with 'use cache' (#86292)
Adds a test case demonstrating that `useActionState` doesn't work correctly when the `'use cache'` function is exported separately, due to wrong function arity information in the server reference information byte. This is currently a limitation of the Next.js compiler, which will be addressed in a future PR. Also cleans up `console.log` from the existing `useActionState` test.
1 parent e66e0ea commit dbfb6c4

File tree

5 files changed

+57
-3
lines changed

5 files changed

+57
-3
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use cache'
2+
3+
const getRandomValue = async () => {
4+
return Math.random()
5+
}
6+
7+
export { getRandomValue }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use client'
2+
3+
import { useActionState } from 'react'
4+
import { getRandomValue } from './cached'
5+
6+
export function Form() {
7+
const [result, formAction, isPending] = useActionState(getRandomValue, -1)
8+
9+
return (
10+
<form action={formAction}>
11+
<button id="submit-button">Submit</button>
12+
<p>{isPending ? 'loading...' : result}</p>
13+
</form>
14+
)
15+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Form } from './form'
2+
3+
export default function Page() {
4+
return <Form />
5+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
'use cache'
22

33
export async function getRandomValue() {
4-
const v = Math.random()
5-
console.log(v)
6-
return v
4+
return Math.random()
75
}

test/e2e/app-dir/use-cache/use-cache.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ describe('use-cache', () => {
499499
'/static-class-method',
500500
withCacheComponents && '/unhandled-promise-regression',
501501
'/use-action-state',
502+
'/use-action-state-separate-export',
502503
'/with-server-action',
503504
].filter(Boolean)
504505
)
@@ -709,6 +710,34 @@ describe('use-cache', () => {
709710
})
710711
})
711712

713+
// TODO: This test doesn't work currently because the compiler doesn't
714+
// properly compute the server reference information byte that includes the
715+
// function arity. Without this information, the client can't optimize the
716+
// arguments it sends to the server, so the (unused) previous state is also
717+
// sent as an argument, leading to cache misses.
718+
it.failing(
719+
'works with useActionState if previousState parameter is not used in "use cache" function (separate export)',
720+
async () => {
721+
const browser = await next.browser('/use-action-state-separate-export')
722+
723+
let value = await browser.elementByCss('p').text()
724+
expect(value).toBe('-1')
725+
726+
await browser.elementByCss('button').click()
727+
728+
await retry(async () => {
729+
value = await browser.elementByCss('p').text()
730+
expect(value).toMatch(/\d\.\d+/)
731+
})
732+
733+
await browser.elementByCss('button').click()
734+
735+
await retry(async () => {
736+
expect(await browser.elementByCss('p').text()).toBe(value)
737+
})
738+
}
739+
)
740+
712741
it('works with "use cache" in method props', async () => {
713742
const browser = await next.browser('/method-props')
714743

0 commit comments

Comments
 (0)