Skip to content

Commit 7146b66

Browse files
committed
Optimise deep equality check and refactor useCerbosRequest
Signed-off-by: Andrew Haines <[email protected]>
1 parent ab8ec9b commit 7146b66

15 files changed

+198
-238
lines changed

docs/react.asyncresult.data.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

docs/react.asyncresult.error.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

docs/react.asyncresult.isloading.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

docs/react.asyncresult.md

Lines changed: 14 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,23 @@
22

33
[Home](./index.md) &gt; [@cerbos/react](./react.md) &gt; [AsyncResult](./react.asyncresult.md)
44

5-
## AsyncResult interface
5+
## AsyncResult type
66

77

88
**Signature:**
99

1010
```typescript
11-
export interface AsyncResult<T>
11+
export type AsyncResult<T> = {
12+
isLoading: true;
13+
data: undefined;
14+
error: undefined;
15+
} | {
16+
isLoading: false;
17+
data: T;
18+
error: undefined;
19+
} | {
20+
isLoading: false;
21+
data: undefined;
22+
error: Error;
23+
};
1224
```
13-
14-
## Properties
15-
16-
<table><thead><tr><th>
17-
18-
Property
19-
20-
21-
</th><th>
22-
23-
Modifiers
24-
25-
26-
</th><th>
27-
28-
Type
29-
30-
31-
</th><th>
32-
33-
Description
34-
35-
36-
</th></tr></thead>
37-
<tbody><tr><td>
38-
39-
[data](./react.asyncresult.data.md)
40-
41-
42-
</td><td>
43-
44-
45-
</td><td>
46-
47-
T \| undefined
48-
49-
50-
</td><td>
51-
52-
53-
</td></tr>
54-
<tr><td>
55-
56-
[error](./react.asyncresult.error.md)
57-
58-
59-
</td><td>
60-
61-
62-
</td><td>
63-
64-
Error \| undefined
65-
66-
67-
</td><td>
68-
69-
70-
</td></tr>
71-
<tr><td>
72-
73-
[isLoading](./react.asyncresult.isloading.md)
74-
75-
76-
</td><td>
77-
78-
79-
</td><td>
80-
81-
boolean
82-
83-
84-
</td><td>
85-
86-
87-
</td></tr>
88-
</tbody></table>

docs/react.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,32 @@ Description
8989
</th></tr></thead>
9090
<tbody><tr><td>
9191

92-
[AsyncResult](./react.asyncresult.md)
92+
[CerbosProviderProps](./react.cerbosproviderprops.md)
9393

9494

9595
</td><td>
9696

9797

9898

9999
</td></tr>
100-
<tr><td>
100+
</tbody></table>
101101

102-
[CerbosProviderProps](./react.cerbosproviderprops.md)
102+
## Type Aliases
103+
104+
<table><thead><tr><th>
105+
106+
Type Alias
107+
108+
109+
</th><th>
110+
111+
Description
112+
113+
114+
</th></tr></thead>
115+
<tbody><tr><td>
116+
117+
[AsyncResult](./react.asyncresult.md)
103118

104119

105120
</td><td>

packages/react/.eslintrc.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
plugins:
2-
- react-hooks
3-
41
extends:
52
- plugin:react-hooks/recommended

packages/react/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@
5353
},
5454
"devDependencies": {
5555
"@types/react": "18.2.67",
56-
"eslint-plugin-react-hooks": "4.6.0",
57-
"react": "18.2.0"
56+
"eslint-plugin-react-hooks": "4.6.0"
5857
},
5958
"publishConfig": {
6059
"access": "public",

packages/react/src/cerbos-provider.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import type {
77
import type { ReactElement, ReactNode } from "react";
88
import { createContext, useMemo } from "react";
99

10+
import { useDeepEqualMemo } from "./use-deep-equal-memo";
11+
1012
export const CerbosContext = createContext<ClientWithPrincipal | undefined>(
1113
undefined,
1214
);
@@ -63,9 +65,12 @@ export function CerbosProvider({
6365
principal,
6466
auxData,
6567
}: CerbosProviderProps): ReactElement {
68+
const principalMemo = useDeepEqualMemo(principal);
69+
const auxDataMemo = useDeepEqualMemo(auxData);
70+
6671
const value = useMemo(
67-
() => client.withPrincipal(principal, auxData),
68-
[auxData, client, principal],
72+
() => client.withPrincipal(principalMemo, auxDataMemo),
73+
[client, principalMemo, auxDataMemo],
6974
);
7075

7176
return (

packages/react/src/deep-equal.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export function deepEqual(a: unknown, b: unknown): boolean {
2+
if (a === b) {
3+
return true;
4+
}
5+
6+
if (
7+
typeof a !== "object" ||
8+
a === null ||
9+
typeof b !== "object" ||
10+
b === null
11+
) {
12+
// one of them is a primitive or null, so if they weren't strictly equal above, then they aren't equal
13+
return false;
14+
}
15+
16+
// they are both non-null objects (arrays are objects too)
17+
18+
if (Array.isArray(a)) {
19+
if (!Array.isArray(b)) {
20+
return false;
21+
}
22+
23+
// they are both arrays
24+
25+
if (a.length !== b.length) {
26+
return false;
27+
}
28+
29+
for (let i = 0; i < a.length; i++) {
30+
if (!deepEqual(a[i], b[i])) {
31+
return false;
32+
}
33+
}
34+
35+
return true;
36+
}
37+
38+
// they are both objects - ignore more complex types like Map, Symbol, Date etc...
39+
40+
const keys = Object.keys(a);
41+
if (keys.length !== Object.keys(b).length) {
42+
return false;
43+
}
44+
45+
for (const key of keys) {
46+
const valueA = (a as Record<string, unknown>)[key];
47+
const valueB = (b as Record<string, unknown>)[key];
48+
49+
if (!deepEqual(valueA, valueB)) {
50+
return false;
51+
}
52+
}
53+
54+
return true;
55+
}

packages/react/src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
export { CerbosProvider } from "./cerbos-provider";
2-
export type { CerbosProviderProps } from "./cerbos-provider";
1+
export { type CerbosProviderProps, CerbosProvider } from "./cerbos-provider";
32
export { useCerbos } from "./use-cerbos";
43
export {
4+
type AsyncResult,
55
useCheckResource,
66
useCheckResources,
77
useIsAllowed,
88
} from "./use-cerbos-request";
9-
export type { AsyncResult } from "./use-cerbos-request";

packages/react/src/is-equal.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)