-
Notifications
You must be signed in to change notification settings - Fork 29.9k
[test] Add failing test for useActionState with 'use cache'
#86292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| 'use cache' | ||
|
|
||
| const getRandomValue = async () => { | ||
| return Math.random() | ||
| } | ||
|
|
||
| export { getRandomValue } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| 'use client' | ||
|
|
||
| import { useActionState } from 'react' | ||
| import { getRandomValue } from './cached' | ||
|
|
||
| export function Form() { | ||
| const [result, formAction, isPending] = useActionState(getRandomValue, -1) | ||
|
|
||
| return ( | ||
| <form action={formAction}> | ||
| <button id="submit-button">Submit</button> | ||
| <p>{isPending ? 'loading...' : result}</p> | ||
| </form> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import { Form } from './form' | ||
|
|
||
| export default function Page() { | ||
| return <Form /> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,5 @@ | ||
| 'use cache' | ||
|
|
||
| export async function getRandomValue() { | ||
| const v = Math.random() | ||
| console.log(v) | ||
| return v | ||
| return Math.random() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -499,6 +499,7 @@ describe('use-cache', () => { | |
| '/static-class-method', | ||
| withCacheComponents && '/unhandled-promise-regression', | ||
| '/use-action-state', | ||
| '/use-action-state-separate-export', | ||
| '/with-server-action', | ||
| ].filter(Boolean) | ||
| ) | ||
|
|
@@ -709,6 +710,34 @@ describe('use-cache', () => { | |
| }) | ||
| }) | ||
|
|
||
| // TODO: This test doesn't work currently because the compiler doesn't | ||
| // properly compute the server reference information byte that includes the | ||
| // function arity. Without this information, the client can't optimize the | ||
| // arguments it sends to the server, so the (unused) previous state is also | ||
| // sent as an argument, leading to cache misses. | ||
| it.failing( | ||
| 'works with useActionState if previousState parameter is not used in "use cache" function (separate export)', | ||
| async () => { | ||
| const browser = await next.browser('/use-action-state-separate-export') | ||
|
|
||
| let value = await browser.elementByCss('p').text() | ||
| expect(value).toBe('-1') | ||
|
|
||
| await browser.elementByCss('button').click() | ||
|
|
||
| await retry(async () => { | ||
| value = await browser.elementByCss('p').text() | ||
| expect(value).toMatch(/\d\.\d+/) | ||
| }) | ||
|
|
||
| await browser.elementByCss('button').click() | ||
|
|
||
| await retry(async () => { | ||
| expect(await browser.elementByCss('p').text()).toBe(value) | ||
| }) | ||
|
Comment on lines
+733
to
+737
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this potentially flaky in case we assert on the content before the form actually goes into pending? I'd instead log in an Effect that we're pending and when the new value comes in. And then assert on those logs. Kinda like we do in our React tests with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that's needed here. See #72506 (comment) In Datadog I could only find failures (for the existing test with the same setup) that seem to be triggered by other failed tests abandoning the job while this test suite was still running, if I understand this correctly. I actually didn't know this can happen, and it kinda skews our flakiness metrics! |
||
| } | ||
| ) | ||
|
|
||
| it('works with "use cache" in method props', async () => { | ||
| const browser = await next.browser('/method-props') | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does that currently work? Do we just send all arguments if the Compiler sees
argumentsor rest parameters?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is handled here:
next.js/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts
Lines 95 to 103 in e66e0ea
We're using the server reference information byte in the server reference ID to filter the arguments that we send to the server.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the compiler can't determine the arity we're sending all arguments unfiltered. So this opts out of the optimization. (Side note: Using
argumentsis forbidden in server functions, which is enforced by the compiler.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the thing I'm interested in. What's setting these bits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is done here:
next.js/crates/next-custom-transforms/src/transforms/server_actions.rs
Lines 279 to 339 in e66e0ea