@@ -1446,6 +1446,80 @@ describe("Atom", () => {
14461446
14471447 unmount2 ( )
14481448 } )
1449+
1450+ it ( "subscriptionRef with runtime recomputes when dependencies change" , async ( ) => {
1451+ vitest . useRealTimers ( )
1452+
1453+ // Test that subscriptionRef atoms properly recompute when their dependencies change
1454+ // This test was added based on a user report that subscriptionRef atoms don't recompute
1455+ // when dependencies accessed via get.some() change.
1456+ const chatIdAtom = Atom . make < Option . Option < string > > ( Option . none ( ) ) . pipe ( Atom . keepAlive )
1457+
1458+ // A regular derived atom using Effect.fnUntraced
1459+ let derivedRecomputes = 0
1460+ const derivedStateAtom = counterRuntime . atom (
1461+ Effect . fnUntraced ( function * ( get : Atom . Context ) {
1462+ const chatId = yield * get . some ( chatIdAtom )
1463+ derivedRecomputes ++
1464+ return chatId
1465+ } )
1466+ )
1467+
1468+ // A subscriptionRef atom that also depends on chatIdAtom
1469+ let subRefRecomputes = 0
1470+ const stateAtom = counterRuntime . subscriptionRef ( ( get ) =>
1471+ Effect . gen ( function * ( ) {
1472+ const chatId = yield * get . some ( chatIdAtom )
1473+ subRefRecomputes ++
1474+ return yield * SubscriptionRef . make ( chatId )
1475+ } )
1476+ )
1477+
1478+ const r = Registry . make ( )
1479+ const unmountDerived = r . mount ( derivedStateAtom )
1480+ const unmountSubRef = r . mount ( stateAtom )
1481+
1482+ // Initially, chatIdAtom is None, so both should fail with NoSuchElementException
1483+ let derivedResult = r . get ( derivedStateAtom )
1484+ let subRefResult = r . get ( stateAtom )
1485+ expect ( derivedRecomputes ) . toEqual ( 0 )
1486+ expect ( subRefRecomputes ) . toEqual ( 0 )
1487+
1488+ // Set chatIdAtom to Some("chat-1")
1489+ r . set ( chatIdAtom , Option . some ( "chat-1" ) )
1490+ await new Promise ( ( resolve ) => resolve ( null ) )
1491+
1492+ derivedResult = r . get ( derivedStateAtom )
1493+ subRefResult = r . get ( stateAtom )
1494+
1495+ assert ( Result . isSuccess ( derivedResult ) )
1496+ expect ( derivedResult . value ) . toEqual ( "chat-1" )
1497+ expect ( derivedRecomputes ) . toEqual ( 1 )
1498+
1499+ assert ( Result . isSuccess ( subRefResult ) )
1500+ expect ( subRefResult . value ) . toEqual ( "chat-1" )
1501+ expect ( subRefRecomputes ) . toEqual ( 1 )
1502+
1503+ // Change chatIdAtom to Some("chat-2") - both atoms should recompute
1504+ r . set ( chatIdAtom , Option . some ( "chat-2" ) )
1505+ await new Promise ( ( resolve ) => resolve ( null ) )
1506+
1507+ derivedResult = r . get ( derivedStateAtom )
1508+ subRefResult = r . get ( stateAtom )
1509+
1510+ // The derived atom should have recomputed
1511+ assert ( Result . isSuccess ( derivedResult ) )
1512+ expect ( derivedResult . value ) . toEqual ( "chat-2" )
1513+ expect ( derivedRecomputes ) . toEqual ( 2 )
1514+
1515+ // The subscriptionRef atom should ALSO have recomputed
1516+ assert ( Result . isSuccess ( subRefResult ) )
1517+ expect ( subRefResult . value ) . toEqual ( "chat-2" )
1518+ expect ( subRefRecomputes ) . toEqual ( 2 )
1519+
1520+ unmountDerived ( )
1521+ unmountSubRef ( )
1522+ } )
14491523} )
14501524
14511525interface BuildCounter {
0 commit comments