Skip to content

Commit 569cb41

Browse files
committed
Return cached subscriptions in useSyncStream
1 parent 77f52c5 commit 569cb41

3 files changed

Lines changed: 28 additions & 14 deletions

File tree

.changeset/few-months-rest.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/react': patch
3+
---
4+
5+
Return cached information from `useSyncStream` if available, potentially reducing flicker.

packages/react/src/hooks/streams.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,30 @@ export function useSyncStream(options: UseSyncStreamOptions): SyncStreamStatus |
3939
const { name, parameters } = options;
4040
const db = usePowerSync();
4141
const status = useStatus();
42-
const [subscription, setSubscription] = useState<SyncStreamSubscription | null>(null);
42+
const stream = useMemo(() => db.syncStream(name, parameters), [name, parameters]);
4343

4444
useEffect(() => {
4545
let active = true;
4646
let subscription: SyncStreamSubscription | null = null;
4747

48-
db.syncStream(name, parameters)
49-
.subscribe(options)
50-
.then((sub) => {
51-
if (active) {
52-
subscription = sub;
53-
setSubscription(sub);
54-
} else {
55-
// The cleanup function already ran, unsubscribe immediately.
56-
sub.unsubscribe();
57-
}
58-
});
48+
stream.subscribe(options).then((sub) => {
49+
if (active) {
50+
subscription = sub;
51+
} else {
52+
// The cleanup function already ran, unsubscribe immediately.
53+
sub.unsubscribe();
54+
}
55+
});
5956

6057
return () => {
6158
active = false;
6259
// If we don't have a subscription yet, it'll still get cleaned up once the promise resolves because we've set
6360
// active to false.
6461
subscription?.unsubscribe();
6562
};
66-
}, [name, parameters]);
63+
}, [stream]);
6764

68-
return subscription && status.forStream(subscription);
65+
return status.forStream(stream) ?? null;
6966
}
7067

7168
/**

packages/react/tests/streams.test.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ describe('stream hooks', () => {
5252
expect(currentStreams()).toStrictEqual([]);
5353
});
5454

55+
it('useSyncStream with cached instance', async () => {
56+
const existingSubscription = await db.syncStream('a').subscribe();
57+
await existingSubscription.unsubscribe();
58+
// The stream is still active at this point due to the TTL.
59+
60+
// This means that useSyncStream should have a result available on the first render.
61+
const { result } = renderHook(() => useSyncStream({ name: 'a' }), {
62+
wrapper: testWrapper
63+
});
64+
expect(result.current).not.toBeNull();
65+
});
66+
5567
it('useQuery can take syncStream instance', async () => {
5668
const { result } = renderHook(() => useQuery('SELECT 1', [], { streams: [db.syncStream('a')] }), {
5769
wrapper: testWrapper

0 commit comments

Comments
 (0)