@@ -19,21 +19,27 @@ describe('useEvent', () => {
19
19
let ReactNoop ;
20
20
let Scheduler ;
21
21
let act ;
22
+ let createContext ;
23
+ let useContext ;
22
24
let useState ;
23
25
let useEvent ;
24
26
let useEffect ;
25
27
let useLayoutEffect ;
28
+ let useMemo ;
26
29
27
30
beforeEach ( ( ) => {
28
31
React = require ( 'react' ) ;
29
32
ReactNoop = require ( 'react-noop-renderer' ) ;
30
33
Scheduler = require ( 'scheduler' ) ;
31
34
32
35
act = require ( 'jest-react' ) . act ;
36
+ createContext = React . createContext ;
37
+ useContext = React . useContext ;
33
38
useState = React . useState ;
34
39
useEvent = React . experimental_useEvent ;
35
40
useEffect = React . useEffect ;
36
41
useLayoutEffect = React . useLayoutEffect ;
42
+ useMemo = React . useMemo ;
37
43
} ) ;
38
44
39
45
function span ( prop ) {
@@ -150,7 +156,7 @@ describe('useEvent', () => {
150
156
} ) ;
151
157
152
158
// @gate enableUseEventHook
153
- it ( ' useLayoutEffect shouldn’ t re-fire when event handlers change' , ( ) => {
159
+ it ( " useLayoutEffect shouldn' t re-fire when event handlers change" , ( ) => {
154
160
class IncrementButton extends React . PureComponent {
155
161
increment = ( ) => {
156
162
this . props . onClick ( ) ;
@@ -235,7 +241,7 @@ describe('useEvent', () => {
235
241
} ) ;
236
242
237
243
// @gate enableUseEventHook
238
- it ( ' useEffect shouldn’ t re-fire when event handlers change' , ( ) => {
244
+ it ( " useEffect shouldn' t re-fire when event handlers change" , ( ) => {
239
245
class IncrementButton extends React . PureComponent {
240
246
increment = ( ) => {
241
247
this . props . onClick ( ) ;
@@ -431,4 +437,159 @@ describe('useEvent', () => {
431
437
act ( ( ) => ReactNoop . render ( < Counter value = { 2 } /> ) ) ;
432
438
expect ( Scheduler ) . toHaveYielded ( [ 'Effect value: 2' , 'Event value: 2' ] ) ;
433
439
} ) ;
440
+
441
+ // @gate enableUseEventHook
442
+ it ( 'integration: implements docs chat room example' , ( ) => {
443
+ function createConnection ( ) {
444
+ let connectedCallback ;
445
+ let timeout ;
446
+ return {
447
+ connect ( ) {
448
+ timeout = setTimeout ( ( ) => {
449
+ if ( connectedCallback ) {
450
+ connectedCallback ( ) ;
451
+ }
452
+ } , 100 ) ;
453
+ } ,
454
+ on ( event , callback ) {
455
+ if ( connectedCallback ) {
456
+ throw Error ( 'Cannot add the handler twice.' ) ;
457
+ }
458
+ if ( event !== 'connected' ) {
459
+ throw Error ( 'Only "connected" event is supported.' ) ;
460
+ }
461
+ connectedCallback = callback ;
462
+ } ,
463
+ disconnect ( ) {
464
+ clearTimeout ( timeout ) ;
465
+ } ,
466
+ } ;
467
+ }
468
+
469
+ function ChatRoom ( { roomId, theme} ) {
470
+ const onConnected = useEvent ( ( ) => {
471
+ Scheduler . unstable_yieldValue ( 'Connected! theme: ' + theme ) ;
472
+ } ) ;
473
+
474
+ useEffect ( ( ) => {
475
+ const connection = createConnection ( roomId ) ;
476
+ connection . on ( 'connected' , ( ) => {
477
+ onConnected ( ) ;
478
+ } ) ;
479
+ connection . connect ( ) ;
480
+ return ( ) => connection . disconnect ( ) ;
481
+ } , [ roomId , onConnected ] ) ;
482
+
483
+ return < Text text = { `Welcome to the ${ roomId } room!` } /> ;
484
+ }
485
+
486
+ act ( ( ) => ReactNoop . render ( < ChatRoom roomId = "general" theme = "light" /> ) ) ;
487
+ expect ( Scheduler ) . toHaveYielded ( [ 'Welcome to the general room!' ] ) ;
488
+ expect ( ReactNoop . getChildren ( ) ) . toEqual ( [
489
+ span ( 'Welcome to the general room!' ) ,
490
+ ] ) ;
491
+
492
+ jest . advanceTimersByTime ( 100 ) ;
493
+ Scheduler . unstable_advanceTime ( 100 ) ;
494
+ expect ( Scheduler ) . toHaveYielded ( [ 'Connected! theme: light' ] ) ;
495
+
496
+ // change roomId only
497
+ act ( ( ) => ReactNoop . render ( < ChatRoom roomId = "music" theme = "light" /> ) ) ;
498
+ expect ( Scheduler ) . toHaveYielded ( [ 'Welcome to the music room!' ] ) ;
499
+ expect ( ReactNoop . getChildren ( ) ) . toEqual ( [
500
+ span ( 'Welcome to the music room!' ) ,
501
+ ] ) ;
502
+ jest . advanceTimersByTime ( 100 ) ;
503
+ Scheduler . unstable_advanceTime ( 100 ) ;
504
+ // should trigger a reconnect
505
+ expect ( Scheduler ) . toHaveYielded ( [ 'Connected! theme: light' ] ) ;
506
+
507
+ // change theme only
508
+ act ( ( ) => ReactNoop . render ( < ChatRoom roomId = "music" theme = "dark" /> ) ) ;
509
+ expect ( Scheduler ) . toHaveYielded ( [ 'Welcome to the music room!' ] ) ;
510
+ expect ( ReactNoop . getChildren ( ) ) . toEqual ( [
511
+ span ( 'Welcome to the music room!' ) ,
512
+ ] ) ;
513
+ jest . advanceTimersByTime ( 100 ) ;
514
+ Scheduler . unstable_advanceTime ( 100 ) ;
515
+ // should not trigger a reconnect
516
+ expect ( Scheduler ) . toFlushWithoutYielding ( ) ;
517
+
518
+ // change roomId only
519
+ act ( ( ) => ReactNoop . render ( < ChatRoom roomId = "travel" theme = "dark" /> ) ) ;
520
+ expect ( Scheduler ) . toHaveYielded ( [ 'Welcome to the travel room!' ] ) ;
521
+ expect ( ReactNoop . getChildren ( ) ) . toEqual ( [
522
+ span ( 'Welcome to the travel room!' ) ,
523
+ ] ) ;
524
+ jest . advanceTimersByTime ( 100 ) ;
525
+ Scheduler . unstable_advanceTime ( 100 ) ;
526
+ // should trigger a reconnect
527
+ expect ( Scheduler ) . toHaveYielded ( [ 'Connected! theme: dark' ] ) ;
528
+ } ) ;
529
+
530
+ // @gate enableUseEventHook
531
+ it ( 'integration: implements the docs logVisit example' , ( ) => {
532
+ class AddToCartButton extends React . PureComponent {
533
+ addToCart = ( ) => {
534
+ this . props . onClick ( ) ;
535
+ } ;
536
+ render ( ) {
537
+ return < Text text = "Add to cart" /> ;
538
+ }
539
+ }
540
+ const ShoppingCartContext = createContext ( null ) ;
541
+
542
+ function AppShell ( { children} ) {
543
+ const [ items , updateItems ] = useState ( [ ] ) ;
544
+ const value = useMemo ( ( ) => ( { items, updateItems} ) , [ items , updateItems ] ) ;
545
+
546
+ return (
547
+ < ShoppingCartContext . Provider value = { value } >
548
+ { children }
549
+ </ ShoppingCartContext . Provider >
550
+ ) ;
551
+ }
552
+
553
+ function Page ( { url} ) {
554
+ const { items, updateItems} = useContext ( ShoppingCartContext ) ;
555
+ const onClick = useEvent ( ( ) => updateItems ( [ ...items , 1 ] ) ) ;
556
+ const numberOfItems = items . length ;
557
+
558
+ const onVisit = useEvent ( visitedUrl => {
559
+ Scheduler . unstable_yieldValue (
560
+ 'url: ' + url + ', numberOfItems: ' + numberOfItems ,
561
+ ) ;
562
+ } ) ;
563
+
564
+ useEffect ( ( ) => {
565
+ onVisit ( url ) ;
566
+ } , [ url ] ) ;
567
+
568
+ return < AddToCartButton onClick = { onClick } ref = { button } /> ;
569
+ }
570
+
571
+ const button = React . createRef ( null ) ;
572
+ act ( ( ) =>
573
+ ReactNoop . render (
574
+ < AppShell >
575
+ < Page url = "/shop/1" />
576
+ </ AppShell > ,
577
+ ) ,
578
+ ) ;
579
+ expect ( Scheduler ) . toHaveYielded ( [
580
+ 'Add to cart' ,
581
+ 'url: /shop/1, numberOfItems: 0' ,
582
+ ] ) ;
583
+ act ( button . current . addToCart ) ;
584
+ expect ( Scheduler ) . toFlushWithoutYielding ( ) ;
585
+
586
+ act ( ( ) =>
587
+ ReactNoop . render (
588
+ < AppShell >
589
+ < Page url = "/shop/2" />
590
+ </ AppShell > ,
591
+ ) ,
592
+ ) ;
593
+ expect ( Scheduler ) . toHaveYielded ( [ 'url: /shop/2, numberOfItems: 1' ] ) ;
594
+ } ) ;
434
595
} ) ;
0 commit comments