Commit dc52e7e 1 parent 910b07b commit dc52e7e Copy full SHA for dc52e7e
File tree 6 files changed +73
-2
lines changed
packages/next/src/shared/lib/router
test/e2e/app-dir/navigation-with-queued-actions
6 files changed +73
-2
lines changed Original file line number Diff line number Diff line change @@ -151,8 +151,9 @@ function dispatchAction(
151
151
// Mark the pending action as discarded (so the state is never applied) and start the navigation action immediately.
152
152
actionQueue . pending . discarded = true
153
153
154
- // Mark this action as the last in the queue
155
- actionQueue . last = newAction
154
+ // The rest of the current queue should still execute after this navigation.
155
+ // (Note that it can't contain any earlier navigations, because we always put those into `actionQueue.pending` by calling `runAction`)
156
+ newAction . next = actionQueue . pending . next
156
157
157
158
// if the pending action was a server action, mark the queue as needing a refresh once events are processed
158
159
if ( actionQueue . pending . payload . type === ACTION_SERVER_ACTION ) {
Original file line number Diff line number Diff line change
1
+ export const metadata = {
2
+ title : 'Next.js' ,
3
+ description : 'Generated by Next.js' ,
4
+ }
5
+
6
+ export default function RootLayout ( {
7
+ children,
8
+ } : {
9
+ children : React . ReactNode
10
+ } ) {
11
+ return (
12
+ < html lang = "en" >
13
+ < body > { children } </ body >
14
+ </ html >
15
+ )
16
+ }
Original file line number Diff line number Diff line change
1
+ 'use client'
2
+
3
+ import { useRouter } from 'next/navigation'
4
+ import { useState } from 'react'
5
+ import { myAction } from './server'
6
+
7
+ export default function Page ( ) {
8
+ const router = useRouter ( )
9
+ const [ text , setText ] = useState ( 'initial' )
10
+
11
+ return (
12
+ < >
13
+ < button
14
+ type = "button"
15
+ onClick = { ( ) => {
16
+ Promise . all ( [ myAction ( 0 ) , myAction ( 1 ) ] ) . then ( ( ) => setText ( 'done' ) )
17
+ setTimeout ( ( ) => {
18
+ router . replace ( '?' )
19
+ } )
20
+ } }
21
+ >
22
+ run actions
23
+ </ button >
24
+ < div id = "action-state" > { text } </ div >
25
+ </ >
26
+ )
27
+ }
Original file line number Diff line number Diff line change
1
+ 'use server'
2
+
3
+ import { setTimeout } from 'timers/promises'
4
+
5
+ export async function myAction ( id : number ) {
6
+ console . log ( `myAction(${ id } ) :: server` )
7
+ await setTimeout ( 100 )
8
+ }
Original file line number Diff line number Diff line change
1
+ import { nextTestSetup } from '../../../lib/e2e-utils'
2
+ import { retry } from '../../../lib/next-test-utils'
3
+
4
+ describe ( 'actions' , ( ) => {
5
+ const { next } = nextTestSetup ( { files : __dirname } )
6
+ it ( 'works' , async ( ) => {
7
+ const browser = await next . browser ( '/' )
8
+ await browser . elementByCss ( 'button' ) . click ( )
9
+ await retry (
10
+ async ( ) => {
11
+ expect ( await browser . elementById ( 'action-state' ) . text ( ) ) . toEqual ( 'done' )
12
+ } ,
13
+ undefined ,
14
+ undefined ,
15
+ 'wait for both actions to finish'
16
+ )
17
+ } )
18
+ } )
Original file line number Diff line number Diff line change
1
+ export default { }
You can’t perform that action at this time.
0 commit comments