@@ -1265,6 +1265,64 @@ describe('useMutableSource', () => {
1265
1265
expect ( Scheduler ) . toHaveYielded ( [ 'x: bar, y: bar' ] ) ;
1266
1266
} ) ;
1267
1267
1268
+ it ( 'getSnapshot changes and then source is mutated in between paint and passive effect phase' , async ( ) => {
1269
+ const source = createSource ( {
1270
+ a : 'foo' ,
1271
+ b : 'bar' ,
1272
+ } ) ;
1273
+ const mutableSource = createMutableSource ( source ) ;
1274
+
1275
+ function mutateB ( newB ) {
1276
+ source . value = {
1277
+ ...source . value ,
1278
+ b : newB ,
1279
+ } ;
1280
+ }
1281
+
1282
+ const getSnapshotA = ( ) => source . value . a ;
1283
+ const getSnapshotB = ( ) => source . value . b ;
1284
+
1285
+ function App ( { getSnapshot} ) {
1286
+ const value = useMutableSource (
1287
+ mutableSource ,
1288
+ getSnapshot ,
1289
+ defaultSubscribe ,
1290
+ ) ;
1291
+
1292
+ Scheduler . unstable_yieldValue ( 'Render: ' + value ) ;
1293
+ React . useEffect ( ( ) => {
1294
+ Scheduler . unstable_yieldValue ( 'Commit: ' + value ) ;
1295
+ } , [ value ] ) ;
1296
+
1297
+ return value ;
1298
+ }
1299
+
1300
+ const root = ReactNoop . createRoot ( ) ;
1301
+ await act ( async ( ) => {
1302
+ root . render ( < App getSnapshot = { getSnapshotA } /> ) ;
1303
+ } ) ;
1304
+ expect ( Scheduler ) . toHaveYielded ( [ 'Render: foo' , 'Commit: foo' ] ) ;
1305
+
1306
+ await act ( async ( ) => {
1307
+ // Switch getSnapshot to read from B instead
1308
+ root . render ( < App getSnapshot = { getSnapshotB } /> ) ;
1309
+ // Render and finish the tree, but yield right after paint, before
1310
+ // the passive effects have fired.
1311
+ expect ( Scheduler ) . toFlushUntilNextPaint ( [ 'Render: bar' ] ) ;
1312
+ // Then mutate B.
1313
+ mutateB ( 'baz' ) ;
1314
+ } ) ;
1315
+ expect ( Scheduler ) . toHaveYielded ( [
1316
+ // Fires the effect from the previous render
1317
+ 'Commit: bar' ,
1318
+ // During that effect, it should detect that the snapshot has changed
1319
+ // and re-render.
1320
+ 'Render: baz' ,
1321
+ 'Commit: baz' ,
1322
+ ] ) ;
1323
+ expect ( root ) . toMatchRenderedOutput ( 'baz' ) ;
1324
+ } ) ;
1325
+
1268
1326
if ( __DEV__ ) {
1269
1327
describe ( 'dev warnings' , ( ) => {
1270
1328
it ( 'should warn if the subscribe function does not return an unsubscribe function' , ( ) => {
0 commit comments