@isograph/react-disposable-state 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-compile-typescript.log +4 -0
- package/README.md +9 -15
- package/dist/ParentCache.d.ts +1 -1
- package/dist/ParentCache.d.ts.map +1 -1
- package/dist/useCachedResponsivePrecommitValue.d.ts +0 -1
- package/dist/useCachedResponsivePrecommitValue.d.ts.map +1 -1
- package/dist/useCachedResponsivePrecommitValue.js +0 -1
- package/dist/useDisposableState.d.ts.map +1 -1
- package/dist/useLazyDisposableState.d.ts.map +1 -1
- package/docs/managing-complex-state.md +32 -28
- package/package.json +6 -5
- package/src/CacheItem.test.ts +5 -5
- package/src/ParentCache.test.ts +2 -2
- package/src/ParentCache.ts +1 -1
- package/src/useCachedResponsivePrecommitValue.test.tsx +3 -3
- package/src/useCachedResponsivePrecommitValue.ts +0 -1
- package/src/useDisposableState.ts +0 -1
- package/src/useLazyDisposableState.test.tsx +1 -0
- package/src/useLazyDisposableState.ts +2 -4
- package/src/useUpdatableDisposableState.test.tsx +2 -2
package/README.md
CHANGED
@@ -84,9 +84,9 @@ A hook that:
|
|
84
84
|
|
85
85
|
```typescript
|
86
86
|
const { state }: { state: T } = useLazyDisposableState<T>(
|
87
|
-
parentCache
|
88
|
-
factory
|
89
|
-
options
|
87
|
+
parentCache,
|
88
|
+
factory,
|
89
|
+
options,
|
90
90
|
);
|
91
91
|
```
|
92
92
|
|
@@ -105,11 +105,9 @@ const {
|
|
105
105
|
state,
|
106
106
|
setState,
|
107
107
|
}: {
|
108
|
-
state: T | null
|
109
|
-
setState: (ItemCleanupPair<T>) => void
|
110
|
-
} = useUpdatableDisposableState<T>(
|
111
|
-
options: ?Options,
|
112
|
-
);
|
108
|
+
state: T | null;
|
109
|
+
setState: (pair: ItemCleanupPair<T>) => void;
|
110
|
+
} = useUpdatableDisposableState<T>(options);
|
113
111
|
```
|
114
112
|
|
115
113
|
### `useDisposableState`
|
@@ -123,13 +121,9 @@ const {
|
|
123
121
|
state,
|
124
122
|
setState,
|
125
123
|
}: {
|
126
|
-
state: T
|
127
|
-
setState: (ItemCleanupPair<T>) => void
|
128
|
-
} = useDisposableState<T>(
|
129
|
-
parentCache: ParentCache<T>,
|
130
|
-
factory: Loader<T>,
|
131
|
-
options: ?Options,
|
132
|
-
);
|
124
|
+
state: T;
|
125
|
+
setState: (pair: ItemCleanupPair<T>) => void;
|
126
|
+
} = useDisposableState<T>(parentCache, factory, options);
|
133
127
|
```
|
134
128
|
|
135
129
|
## Miscellaneous notes
|
package/dist/ParentCache.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ParentCache.d.ts","sourceRoot":"","sources":["../src/ParentCache.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"ParentCache.d.ts","sourceRoot":"","sources":["../src/ParentCache.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,OAAO,EACP,eAAe,EAChB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAsC,MAAM,aAAa,CAAC;AAK5E;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,WAAW,CAAC,CAAC;IACxB,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;gBAI3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAI/B;;;;;;;;;OASG;IACH,8BAA8B,IAAI,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI;IAM3D,+BAA+B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC;IAM/D,OAAO,CAAC,4BAA4B;IA4BpC,KAAK;IAIL,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAExB;IAED,OAAO,IAAI,OAAO;CAGnB"}
|
@@ -31,7 +31,6 @@ import { ParentCache } from './ParentCache';
|
|
31
31
|
*
|
32
32
|
* Passing a different onCommit:
|
33
33
|
* - Passing a different onCommit has no effect, except for during commit.
|
34
|
-
*
|
35
34
|
*/
|
36
35
|
export declare function useCachedResponsivePrecommitValue<T>(parentCache: ParentCache<T>, onCommit: (pair: ItemCleanupPair<T>) => void): {
|
37
36
|
state: T;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useCachedResponsivePrecommitValue.d.ts","sourceRoot":"","sources":["../src/useCachedResponsivePrecommitValue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C
|
1
|
+
{"version":3,"file":"useCachedResponsivePrecommitValue.d.ts","sourceRoot":"","sources":["../src/useCachedResponsivePrecommitValue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,iCAAiC,CAAC,CAAC,EACjD,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,EAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG,IAAI,CA8DrB"}
|
@@ -33,7 +33,6 @@ const react_1 = require("react");
|
|
33
33
|
*
|
34
34
|
* Passing a different onCommit:
|
35
35
|
* - Passing a different onCommit has no effect, except for during commit.
|
36
|
-
*
|
37
36
|
*/
|
38
37
|
function useCachedResponsivePrecommitValue(parentCache, onCommit) {
|
39
38
|
// TODO: there should be two APIs. One in which we always re-render if the
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useDisposableState.d.ts","sourceRoot":"","sources":["../src/useDisposableState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
1
|
+
{"version":3,"file":"useDisposableState.d.ts","sourceRoot":"","sources":["../src/useDisposableState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAEL,eAAe,EAEhB,MAAM,+BAA+B,CAAC;AAEvC,KAAK,sCAAsC,CAAC,CAAC,IAAI;IAC/C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,KAAK,IAAI,CAAC;CACxE,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,KAAK,EAC1C,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,GAC1B,sCAAsC,CAAC,CAAC,CAAC,CAgE3C"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useLazyDisposableState.d.ts","sourceRoot":"","sources":["../src/useLazyDisposableState.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"useLazyDisposableState.d.ts","sourceRoot":"","sources":["../src/useLazyDisposableState.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GACpD;IACD,KAAK,EAAE,CAAC,CAAC;CACV,CAoCA"}
|
@@ -13,17 +13,19 @@ Consider using `useUpdatableDisposableState` state to manage an array of disposa
|
|
13
13
|
The behavior of `useUpdatableDisposableState` is to entirely dispose of all previously-held items after a new item is set in state. So, if we had
|
14
14
|
|
15
15
|
```js
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
const component = () => {
|
17
|
+
const { state, setState } = useUpdatableDisposableState();
|
18
|
+
// assume state === [item1], and the cleanup function will dispose item1
|
19
|
+
|
20
|
+
const addItem2ToState = () => {
|
21
|
+
setState([item1, item2], () => {
|
22
|
+
disposeItem1();
|
23
|
+
disposeItem2();
|
24
|
+
});
|
25
|
+
};
|
26
|
+
|
27
|
+
return makePrettyJSX(state[0]);
|
24
28
|
};
|
25
|
-
|
26
|
-
return makePrettyJSX(state[0]);
|
27
29
|
```
|
28
30
|
|
29
31
|
In the above, `item1` would be disposed after the state was updated to be `[item1, item2]`. Meaning, the hook returns an item that has already been disposed. Clearly, this will not do.
|
@@ -51,25 +53,27 @@ Given an undisposed active reference `r1`, one can get a new active reference `r
|
|
51
53
|
Let's use reference counted pointers in the example.
|
52
54
|
|
53
55
|
```js
|
54
|
-
const
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
const
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
const component = () => {
|
57
|
+
const { state, setState } = useUpdatableDisposableState();
|
58
|
+
// assume state === [item1activeReference], and the cleanup function will dispose that active reference
|
59
|
+
|
60
|
+
const addItem2ToState = () => {
|
61
|
+
const [item2, disposeItem2] = createDisposeItem2();
|
62
|
+
const [item2ActiveReference, disposeItem2ActiveReference] =
|
63
|
+
createReferenceCountedPointer([item2, disposeItem2]);
|
64
|
+
|
65
|
+
// get a new active reference to the existing item1
|
66
|
+
const [item1ActiveReference, disposeItem1ActiveReference] = nullthrows(
|
67
|
+
state[0].cloneIfNotDisposed(),
|
68
|
+
);
|
69
|
+
setState([item1ActiveReference, item2ActiveReference], () => {
|
70
|
+
disposeItem1ActiveReference();
|
71
|
+
disposeItem2ActiveReference();
|
72
|
+
});
|
73
|
+
};
|
74
|
+
|
75
|
+
return makePrettyJSX(nullthrows(state[0].getItemIfNotDisposed()));
|
70
76
|
};
|
71
|
-
|
72
|
-
return makePrettyJSX(nullthrows(state[0].getItemIfNotDisposed()));
|
73
77
|
```
|
74
78
|
|
75
79
|
Not the most ergonomic, but it does the job.
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@isograph/react-disposable-state",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.1",
|
4
4
|
"description": "Primitives for managing disposable state in React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -8,20 +8,21 @@
|
|
8
8
|
"author": "Isograph Labs",
|
9
9
|
"license": "MIT",
|
10
10
|
"scripts": {
|
11
|
-
"compile": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
|
11
|
+
"compile-typescript": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
|
12
12
|
"compile-watch": "tsc -p tsconfig.pkg.json --watch",
|
13
13
|
"test": "vitest run",
|
14
14
|
"test-watch": "vitest watch",
|
15
15
|
"coverage": "vitest run --coverage",
|
16
16
|
"note": "WE SHOULD ALSO TEST HERE",
|
17
|
-
"prepack": "pnpm run compile",
|
18
|
-
"tsc": "tsc"
|
17
|
+
"prepack": "pnpm run compile-typescript",
|
18
|
+
"tsc": "tsc",
|
19
|
+
"tsc-force": "tsc --build --clean && tsc --build --force"
|
19
20
|
},
|
20
21
|
"dependencies": {
|
21
22
|
"@isograph/disposable-types": "*"
|
22
23
|
},
|
23
24
|
"peerDependencies": {
|
24
|
-
"react": "18.
|
25
|
+
"react": "^18.0.0 || ^19.0.0"
|
25
26
|
},
|
26
27
|
"devDependencies": {
|
27
28
|
"@types/react": "18.3.1",
|
package/src/CacheItem.test.ts
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
+
import { ItemCleanupPair } from '@isograph/disposable-types';
|
1
2
|
import {
|
2
|
-
|
3
|
+
afterEach,
|
3
4
|
assert,
|
4
|
-
test,
|
5
|
-
vi,
|
6
5
|
beforeEach,
|
7
|
-
|
6
|
+
describe,
|
8
7
|
expect,
|
8
|
+
test,
|
9
|
+
vi,
|
9
10
|
} from 'vitest';
|
10
11
|
import {
|
11
12
|
CacheItem,
|
12
13
|
CacheItemState,
|
13
14
|
createTemporarilyRetainedCacheItem,
|
14
15
|
} from './CacheItem';
|
15
|
-
import { ItemCleanupPair } from '@isograph/disposable-types';
|
16
16
|
|
17
17
|
function getState<T>(cacheItem: CacheItem<T>): CacheItemState<T> {
|
18
18
|
return (cacheItem as any).__state as CacheItemState<T>;
|
package/src/ParentCache.test.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
import { describe, assert, test, vi, expect } from 'vitest';
|
2
|
-
import { ParentCache } from './ParentCache';
|
3
1
|
import { ItemCleanupPair } from '@isograph/disposable-types';
|
2
|
+
import { assert, describe, expect, test, vi } from 'vitest';
|
4
3
|
import { CacheItem } from './CacheItem';
|
4
|
+
import { ParentCache } from './ParentCache';
|
5
5
|
|
6
6
|
function getValue<T>(cache: ParentCache<T>): CacheItem<T> | null {
|
7
7
|
return (cache as any).__cacheItem as CacheItem<T> | null;
|
package/src/ParentCache.ts
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
import { CacheItem, createTemporarilyRetainedCacheItem } from './CacheItem';
|
2
1
|
import {
|
3
2
|
CleanupFn,
|
4
3
|
Factory,
|
5
4
|
ItemCleanupPair,
|
6
5
|
} from '@isograph/disposable-types';
|
6
|
+
import { CacheItem, createTemporarilyRetainedCacheItem } from './CacheItem';
|
7
7
|
|
8
8
|
// TODO convert cache impl to a getter and setter and free functions
|
9
9
|
// TODO accept options that get passed to CacheItem
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import { describe, test, vi, expect, assert } from 'vitest';
|
2
|
-
import { ParentCache } from './ParentCache';
|
3
1
|
import { ItemCleanupPair } from '@isograph/disposable-types';
|
4
|
-
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
|
5
2
|
import React from 'react';
|
6
3
|
import { create } from 'react-test-renderer';
|
4
|
+
import { assert, describe, expect, test, vi } from 'vitest';
|
7
5
|
import { CacheItem, CacheItemState } from './CacheItem';
|
6
|
+
import { ParentCache } from './ParentCache';
|
7
|
+
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
|
8
8
|
|
9
9
|
function getItem<T>(cache: ParentCache<T>): CacheItem<T> | null {
|
10
10
|
return (cache as any).__cacheItem;
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { ItemCleanupPair } from '@isograph/disposable-types';
|
2
2
|
import { useEffect, useRef } from 'react';
|
3
3
|
import { ParentCache } from './ParentCache';
|
4
|
-
|
5
4
|
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
|
6
5
|
import {
|
7
6
|
UNASSIGNED_STATE,
|
@@ -4,6 +4,7 @@ import { create } from 'react-test-renderer';
|
|
4
4
|
import { describe, expect, test, vi } from 'vitest';
|
5
5
|
import { ParentCache } from './ParentCache';
|
6
6
|
import { useLazyDisposableState } from './useLazyDisposableState';
|
7
|
+
|
7
8
|
function createCache<T>(value: T) {
|
8
9
|
const disposeItem = vi.fn();
|
9
10
|
const factory = vi.fn(() => {
|
@@ -1,12 +1,10 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
import { useEffect, useRef } from 'react';
|
4
|
-
|
5
3
|
import type { ItemCleanupPair } from '@isograph/isograph-disposable-types';
|
4
|
+
import { useEffect, useRef } from 'react';
|
6
5
|
import { ParentCache } from './ParentCache';
|
7
|
-
|
8
|
-
import { type UnassignedState } from './useUpdatableDisposableState';
|
9
6
|
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
|
7
|
+
import { type UnassignedState } from './useUpdatableDisposableState';
|
10
8
|
|
11
9
|
/**
|
12
10
|
* useLazyDisposableState<T>
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import { describe, test, vi, expect } from 'vitest';
|
2
1
|
import React from 'react';
|
3
2
|
import { create } from 'react-test-renderer';
|
3
|
+
import { describe, expect, test, vi } from 'vitest';
|
4
4
|
import {
|
5
|
-
useUpdatableDisposableState,
|
6
5
|
UNASSIGNED_STATE,
|
6
|
+
useUpdatableDisposableState,
|
7
7
|
} from './useUpdatableDisposableState';
|
8
8
|
|
9
9
|
function Suspender({ promise, isResolvedRef }) {
|