@@ -30,6 +30,7 @@ let React;
30
30
let ReactDOMServer ;
31
31
let ReactServerDOMServer ;
32
32
let ReactServerDOMClient ;
33
+ let useFormState ;
33
34
34
35
describe ( 'ReactFlightDOMForm' , ( ) => {
35
36
beforeEach ( ( ) => {
@@ -47,6 +48,7 @@ describe('ReactFlightDOMForm', () => {
47
48
ReactServerDOMServer = require ( 'react-server-dom-webpack/server.edge' ) ;
48
49
ReactServerDOMClient = require ( 'react-server-dom-webpack/client.edge' ) ;
49
50
ReactDOMServer = require ( 'react-dom/server.edge' ) ;
51
+ useFormState = require ( 'react-dom' ) . experimental_useFormState ;
50
52
container = document . createElement ( 'div' ) ;
51
53
document . body . appendChild ( container ) ;
52
54
} ) ;
@@ -308,4 +310,82 @@ describe('ReactFlightDOMForm', () => {
308
310
expect ( result ) . toBe ( 'hello' ) ;
309
311
expect ( foo ) . toBe ( 'barobject' ) ;
310
312
} ) ;
313
+
314
+ // @gate enableFormActions
315
+ // @gate enableAsyncActions
316
+ it ( "useFormState's dispatch binds the initial state to the provided action" , async ( ) => {
317
+ let serverActionResult = null ;
318
+
319
+ const serverAction = serverExports ( function action ( prevState , formData ) {
320
+ const newState = {
321
+ count : prevState . count + parseInt ( formData . get ( 'incrementAmount' ) , 10 ) ,
322
+ } ;
323
+ serverActionResult = newState ;
324
+ return newState ;
325
+ } ) ;
326
+
327
+ const initialState = { count : 1 } ;
328
+ function Client ( { action} ) {
329
+ const [ state , dispatch ] = useFormState ( action , initialState ) ;
330
+ return (
331
+ < form action = { dispatch } >
332
+ < span > Count: { state . count } </ span >
333
+ < input type = "text" name = "incrementAmount" defaultValue = "5" />
334
+ </ form >
335
+ ) ;
336
+ }
337
+ const ClientRef = await clientExports ( Client ) ;
338
+
339
+ const rscStream = ReactServerDOMServer . renderToReadableStream (
340
+ < ClientRef action = { serverAction } /> ,
341
+ webpackMap ,
342
+ ) ;
343
+ const response = ReactServerDOMClient . createFromReadableStream ( rscStream ) ;
344
+ const ssrStream = await ReactDOMServer . renderToReadableStream ( response ) ;
345
+ await readIntoContainer ( ssrStream ) ;
346
+
347
+ const form = container . firstChild ;
348
+ const span = container . getElementsByTagName ( 'span' ) [ 0 ] ;
349
+ expect ( span . textContent ) . toBe ( 'Count: 1' ) ;
350
+
351
+ await submit ( form ) ;
352
+ expect ( serverActionResult . count ) . toBe ( 6 ) ;
353
+ } ) ;
354
+
355
+ // @gate enableFormActions
356
+ // @gate enableAsyncActions
357
+ it ( "useFormState can change the action's target with the `permalink` argument" , async ( ) => {
358
+ const serverAction = serverExports ( function action ( prevState ) {
359
+ return { state : prevState . count + 1 } ;
360
+ } ) ;
361
+
362
+ const initialState = { count : 1 } ;
363
+ function Client ( { action} ) {
364
+ const [ state , dispatch ] = useFormState (
365
+ action ,
366
+ initialState ,
367
+ '/permalink' ,
368
+ ) ;
369
+ return (
370
+ < form action = { dispatch } >
371
+ < span > Count: { state . count } </ span >
372
+ </ form >
373
+ ) ;
374
+ }
375
+ const ClientRef = await clientExports ( Client ) ;
376
+
377
+ const rscStream = ReactServerDOMServer . renderToReadableStream (
378
+ < ClientRef action = { serverAction } /> ,
379
+ webpackMap ,
380
+ ) ;
381
+ const response = ReactServerDOMClient . createFromReadableStream ( rscStream ) ;
382
+ const ssrStream = await ReactDOMServer . renderToReadableStream ( response ) ;
383
+ await readIntoContainer ( ssrStream ) ;
384
+
385
+ const form = container . firstChild ;
386
+ const span = container . getElementsByTagName ( 'span' ) [ 0 ] ;
387
+ expect ( span . textContent ) . toBe ( 'Count: 1' ) ;
388
+
389
+ expect ( form . target ) . toBe ( '/permalink' ) ;
390
+ } ) ;
311
391
} ) ;
0 commit comments