@@ -121,4 +121,98 @@ describe('ReactTestRenderer', () => {
121
121
expect ( root . toJSON ( ) . children ) . toEqual ( [ 'dynamic' ] ) ;
122
122
} ) ;
123
123
} ) ;
124
+
125
+ it ( 'repro for bug with useEffect synchronization' , ( ) => {
126
+ const ListContext = React . createContext ( null ) ;
127
+ const SelectionContext = React . createContext ( null ) ;
128
+
129
+ function List ( props ) {
130
+ const [ expanded , setExpanded ] = React . useState ( new Set ( ) ) ;
131
+ const listContext = React . useMemo ( ( ) => {
132
+ return {
133
+ onExpanded ( id ) {
134
+ setExpanded ( prevExpanded => new Set ( [ ...prevExpanded , id ] ) ) ;
135
+ } ,
136
+ } ;
137
+ } , [ ] ) ;
138
+ const selectionContext = React . useMemo ( ( ) => {
139
+ return {
140
+ expanded,
141
+ } ;
142
+ } , [ expanded ] ) ;
143
+ return (
144
+ < ListContext . Provider value = { listContext } >
145
+ < SelectionContext . Provider value = { selectionContext } >
146
+ { props . children }
147
+ </ SelectionContext . Provider >
148
+ </ ListContext . Provider >
149
+ ) ;
150
+ }
151
+
152
+ function ListItem ( props ) {
153
+ const { onExpanded} = React . useContext ( ListContext ) ;
154
+ const selectionContext = React . useContext ( SelectionContext ) ;
155
+ const isExpanded = selectionContext . expanded . has ( props . id ) ;
156
+ const didInitiallyExpand = React . useRef ( false ) ;
157
+ const shouldInitiallyExpand =
158
+ props . initiallyExpanded && didInitiallyExpand . current === false ;
159
+ const id = props . id ;
160
+
161
+ React . useEffect ( ( ) => {
162
+ if ( shouldInitiallyExpand ) {
163
+ didInitiallyExpand . current = true ;
164
+ onExpanded ( id ) ;
165
+ }
166
+ } , [ shouldInitiallyExpand , onExpanded , id ] ) ;
167
+
168
+ const expand = React . useCallback ( ( ) => {
169
+ onExpanded ( id ) ;
170
+ } , [ id ] ) ;
171
+
172
+ return isExpanded ? (
173
+ < div > { props . children } </ div >
174
+ ) : (
175
+ < div onClick = { expand } > Expand</ div >
176
+ ) ;
177
+ }
178
+
179
+ function Component ( ) {
180
+ return (
181
+ < List >
182
+ < ListItem id = "1" initiallyExpanded = { true } >
183
+ Item 1
184
+ </ ListItem >
185
+ < ListItem id = "2" initiallyExpanded = { true } >
186
+ Item 2
187
+ </ ListItem >
188
+ < ListItem id = "3" initiallyExpanded = { false } >
189
+ Item 3
190
+ </ ListItem >
191
+ </ List >
192
+ ) ;
193
+ }
194
+
195
+ let renderer ;
196
+ ReactTestRenderer . act ( ( ) => {
197
+ renderer = ReactTestRenderer . create ( < Component /> ) ;
198
+ } ) ;
199
+ const serialized = renderer . toJSON ( ) ;
200
+ expect ( serialized ) . toMatchInlineSnapshot ( `
201
+ [
202
+ <div
203
+ onClick={[Function]}
204
+ >
205
+ Expand
206
+ </div>,
207
+ <div>
208
+ Item 2
209
+ </div>,
210
+ <div
211
+ onClick={[Function]}
212
+ >
213
+ Expand
214
+ </div>,
215
+ ]
216
+ ` ) ;
217
+ } ) ;
124
218
} ) ;
0 commit comments