-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathuse-entity-private.tsx
More file actions
74 lines (66 loc) · 2.59 KB
/
Copy pathuse-entity-private.tsx
File metadata and controls
74 lines (66 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { Entity, type Id } from '@graphprotocol/hypergraph';
import * as Schema from 'effect/Schema';
import { useRef, useSyncExternalStore } from 'react';
import { useHypergraphSpaceInternal } from './use-hypergraph-space-internal.js';
import { useSubscribeToSpaceAndGetHandle } from './use-subscribe-to-space.js';
export function useEntityPrivate<const S extends Schema.Schema.AnyNoContext>(
type: S,
params: {
id: string | Id;
enabled?: boolean;
space?: string;
include?: Entity.EntityInclude<S> | undefined;
},
) {
const { space: spaceFromContext } = useHypergraphSpaceInternal();
const { space: spaceFromParams, include, id, enabled = true } = params;
const handle = useSubscribeToSpaceAndGetHandle({ spaceId: spaceFromParams ?? spaceFromContext, enabled });
const prevEntityRef = useRef<{
data: Entity.Entity<S> | undefined;
invalidEntity: Entity.InvalidEntity | undefined;
isPending: boolean;
isError: boolean;
}>({ data: undefined, invalidEntity: undefined, isPending: false, isError: false });
const equals = Schema.equivalence(type);
const subscribe = (callback: () => void) => {
if (!handle || !enabled) {
return () => {};
}
const handleChange = () => {
callback();
};
const handleDelete = () => {
callback();
};
handle.on('change', handleChange);
handle.on('delete', handleDelete);
return () => {
handle.off('change', handleChange);
handle.off('delete', handleDelete);
};
};
return useSyncExternalStore(subscribe, () => {
if (!handle || !enabled) {
return prevEntityRef.current;
}
const doc = handle.doc();
if (doc === undefined) {
return prevEntityRef.current;
}
const found = Entity.findOne(handle, type, include)(id);
if (found === undefined && prevEntityRef.current.data !== undefined) {
// entity was maybe deleted, delete from the ref
prevEntityRef.current = { data: undefined, invalidEntity: undefined, isPending: false, isError: false };
} else if (found !== undefined && prevEntityRef.current.data === undefined) {
prevEntityRef.current = { data: found, invalidEntity: undefined, isPending: false, isError: false };
} else if (
found !== undefined &&
prevEntityRef.current.data !== undefined &&
!equals(found, prevEntityRef.current.data)
) {
// found and ref have a value, compare for equality, if they are not equal, update the ref and return
prevEntityRef.current = { data: found, invalidEntity: undefined, isPending: false, isError: false };
}
return prevEntityRef.current;
});
}