Skip to content

Commit 646a058

Browse files
committed
move document subscription to be managed by subscribeToFindMany
1 parent 533a620 commit 646a058

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

packages/hypergraph-react/src/HypergraphSpaceContext.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type { AnyDocumentId, DocHandle, Repo } from '@automerge/automerge-repo';
44
import { useRepo } from '@automerge/automerge-repo-react-hooks';
55
import { Entity, Utils } from '@graphprotocol/hypergraph';
6-
import { type DocumentContent, subscribeToDocumentChanges } from '@graphprotocol/hypergraph/Entity';
6+
import type { DocumentContent } from '@graphprotocol/hypergraph/Entity';
77
import * as Schema from 'effect/Schema';
88
import { type ReactNode, createContext, useContext, useEffect, useRef, useState, useSyncExternalStore } from 'react';
99

@@ -12,7 +12,6 @@ export type HypergraphContext = {
1212
repo: Repo;
1313
id: AnyDocumentId;
1414
handle: DocHandle<Entity.DocumentContent>;
15-
unsubscribeChangeListener: () => void;
1615
};
1716

1817
export const HypergraphReactContext = createContext<HypergraphContext | undefined>(undefined);
@@ -32,28 +31,17 @@ export function HypergraphProvider({ space, children }: { space: string; childre
3231

3332
let current = ref.current;
3433
if (current === undefined || space !== current.space || repo !== current.repo) {
35-
current?.unsubscribeChangeListener(); // unsubscribe from the previous space when switching to a new space
36-
3734
const id = Utils.idToAutomergeId(space) as AnyDocumentId;
3835
const handle = repo.find<DocumentContent>(id);
39-
const unsubscribeChangeListener = subscribeToDocumentChanges(handle);
4036

4137
current = ref.current = {
4238
space,
4339
repo,
4440
id,
4541
handle,
46-
unsubscribeChangeListener,
4742
};
4843
}
4944

50-
// biome-ignore lint/correctness/useExhaustiveDependencies: no need for dependencies as the unsubscribe is called from the ref
51-
useEffect(() => {
52-
return () => {
53-
current?.unsubscribeChangeListener(); // unsubscribe from the previous space when the component unmounts
54-
};
55-
}, []);
56-
5745
return <HypergraphReactContext.Provider value={current}>{children}</HypergraphReactContext.Provider>;
5846
}
5947

packages/hypergraph/src/Entity.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ type DecodedEntitiesCache = Map<
101101

102102
const decodedEntitiesCache: DecodedEntitiesCache = new Map();
103103

104+
const documentChangeListener: {
105+
subscribedQueriesCount: number;
106+
unsubscribe: undefined | (() => void);
107+
} = {
108+
subscribedQueriesCount: 0,
109+
unsubscribe: undefined,
110+
};
111+
104112
export const subscribeToDocumentChanges = (handle: DocHandle<DocumentContent>) => {
105113
const onChange = ({ patches, doc }: { patches: Array<Patch>; doc: DocumentContent }) => {
106114
const changedEntities = new Set<string>();
@@ -327,9 +335,16 @@ export function subscribeToFindMany<const S extends AnyNoContext>(
327335

328336
const unsubscribe = () => {
329337
const query = decodedEntitiesCache.get(typeName)?.queries.get(queryKey);
330-
if (!query || !query.listeners) return;
331-
query.listeners = query.listeners.filter((cachedListener) => cachedListener !== listener);
332-
console.log('unsubscribe query', query.listeners);
338+
if (query?.listeners) {
339+
query.listeners = query.listeners.filter((cachedListener) => cachedListener !== listener);
340+
console.log('unsubscribe query', query.listeners);
341+
}
342+
343+
documentChangeListener.subscribedQueriesCount--;
344+
if (documentChangeListener.subscribedQueriesCount === 0) {
345+
documentChangeListener.unsubscribe?.();
346+
documentChangeListener.unsubscribe = undefined;
347+
}
333348
};
334349

335350
const entities = findMany(handle, type);
@@ -375,6 +390,11 @@ export function subscribeToFindMany<const S extends AnyNoContext>(
375390
});
376391
}
377392

393+
if (documentChangeListener.subscribedQueriesCount === 0) {
394+
documentChangeListener.unsubscribe = subscribeToDocumentChanges(handle);
395+
}
396+
documentChangeListener.subscribedQueriesCount++;
397+
378398
return { listener, getEntities, unsubscribe };
379399
}
380400

0 commit comments

Comments
 (0)