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