File tree Expand file tree Collapse file tree 2 files changed +92
-0
lines changed Expand file tree Collapse file tree 2 files changed +92
-0
lines changed Original file line number Diff line number Diff line change 1+ import  React ,  { 
2+  createContext , 
3+  useContext , 
4+  useState , 
5+  useMemo , 
6+  useRef , 
7+  useCallback 
8+ }  from  'react' 
9+ import  renderPrepass  from  '..' 
10+ 
11+ const  CONCURRENCY  =  2 
12+ 
13+ const  Context  =  createContext ( {  test : 3 ,  promise : null ,  resolved : false  } ) 
14+ 
15+ function  makeApp ( )  { 
16+  return  < App  /> 
17+ } 
18+ 
19+ function  App ( )  { 
20+  const  [ state ,  setState ]  =  useState ( ( )  =>  ( { 
21+  test : Math . random ( ) , 
22+  promise : null , 
23+  resolved : false 
24+  } ) ) 
25+  const  refresh  =  ( )  => 
26+  setState ( {  test : Math . random ( ) ,  promise : null ,  resolved : false  } ) 
27+ 
28+  return  ( 
29+  < Context . Provider  value = { {  ...state ,  refresh } } > 
30+  < Outer  /> 
31+  </ Context . Provider > 
32+  ) 
33+ } 
34+ 
35+ function  Outer ( )  { 
36+  useRef ( { 
37+  test : 1 
38+  } ) 
39+ 
40+  const  [ ,  refresh ]  =  useSuspenseHook ( ) 
41+ 
42+  useMemo ( ( )  =>  { 
43+  return  {  a : 1 ,  b : 2  } 
44+  } ,  [ ] ) 
45+ 
46+  return  ( 
47+  < div > 
48+  < button  onClick = { refresh } > Refresh</ button > 
49+  < Inner  /> 
50+  </ div > 
51+  ) 
52+ } 
53+ 
54+ function  useSuspenseHook ( )  { 
55+  const  context  =  useContext ( Context ) 
56+ 
57+  useRef ( { 
58+  test : 1 
59+  } ) 
60+ 
61+  if  ( ! context . resolved  &&  ! context . promise )  { 
62+  context . promise  =  new  Promise ( resolve  => 
63+  setTimeout ( resolve ,  Math . floor ( 30  +  Math . random ( )  *  50 ) ) 
64+  ) . then ( ( )  =>  { 
65+  context . resolved  =  true 
66+  context . promise  =  null 
67+  } ) 
68+  } 
69+ 
70+  if  ( context . promise )  throw  context . promise 
71+ 
72+  return  [ true ,  context . refresh ] 
73+ } 
74+ 
75+ function  Inner ( )  { 
76+  const  [ state ]  =  useState ( {  a : 3  } ) 
77+ 
78+  useCallback ( ( )  =>  { 
79+  return  state 
80+  } ,  [ state ] ) 
81+ 
82+  return  < h4 > Inner</ h4 > 
83+ } 
84+ 
85+ test ( 'concurrency' ,  ( )  =>  { 
86+  return  expect ( 
87+  Promise . all ( 
88+  new  Array ( CONCURRENCY ) . fill ( 0 ) . map ( ( )  =>  renderPrepass ( makeApp ( ) ) ) 
89+  ) 
90+  ) . resolves . not . toThrow ( ) 
91+ } ) 
Original file line number Diff line number Diff line change @@ -113,6 +113,7 @@ export function renderWithHooks(
113113 props : any , 
114114 refOrContext : any 
115115) : any  { 
116+  workInProgressHook  =  null 
116117 let  children  =  Component ( props ,  refOrContext ) 
117118
118119 // NOTE: Excessive rerenders won't throw but will instead abort rendering 
                         You can’t perform that action at this time. 
           
                  
0 commit comments