-
Notifications
You must be signed in to change notification settings - Fork 6
/
useResourceProperty.ts
80 lines (69 loc) · 1.94 KB
/
useResourceProperty.ts
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
75
76
77
78
79
80
import { id, normalizeType } from "link-lib";
import React from "react";
import { calculatedValueChanged } from "../helpers";
import { toReturnType } from "../hocs/link/toReturnType";
import {
DataOpts,
defaultPropertyOptions,
LaxNode,
LaxProperty,
LinkReduxLRSType,
OutputTypeFromOpts,
OutputTypeFromReturnType,
ReturnType,
} from "../types";
import { useDataInvalidation } from "./useDataInvalidation";
import { useLRS } from "./useLRS";
const arrayReturnTypes = [
ReturnType.AllTerms,
ReturnType.AllValues,
ReturnType.AllLiterals,
];
const emptyOutput = <T extends DataOpts>(opts: T): OutputTypeFromOpts<T> => {
return (arrayReturnTypes.includes(opts.returnType) ? [] : undefined) as OutputTypeFromOpts<T>;
};
const calculate = <T extends DataOpts>(
lrs: LinkReduxLRSType,
subject: LaxNode,
property: LaxProperty,
opts: T,
): OutputTypeFromOpts<T> => {
if (!subject) {
return emptyOutput(opts);
}
const props = lrs.getResourcePropertyRaw(
subject,
property,
);
return toReturnType(opts.returnType, props);
};
export function useResourceProperty<
T extends DataOpts = DataOpts,
>(
subject: LaxNode,
property: LaxProperty,
opts?: T,
): OutputTypeFromOpts<T, OutputTypeFromReturnType<ReturnType.AllTerms>> {
const optsOrDefault = opts || defaultPropertyOptions as T;
const lrs = useLRS();
const properties = property ? normalizeType(property) : [];
const lastUpdate = useDataInvalidation([subject, ...properties]);
const [
value,
setValue,
] = React.useState(() => calculate<T>(lrs, subject, properties, optsOrDefault));
React.useEffect(() => {
const returnValue = calculate(lrs, subject, properties, optsOrDefault);
if (calculatedValueChanged(value, returnValue)) {
setValue(returnValue);
}
}, [
lrs,
subject ? id(subject) : undefined,
properties
.map((p) => id(p))
.reduce((acc, next) => acc + next, 0),
lastUpdate,
]);
return value;
}