@isograph/react-disposable-state 0.5.2 → 0.5.4
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-libs.log +5 -5
- package/.turbo/turbo-tsc.log +5 -0
- package/README.md +19 -0
- package/dist/{CacheItem.js → CacheItem.cjs} +11 -8
- package/dist/{CacheItem.d.ts → CacheItem.d.cts} +1 -1
- package/dist/CacheItem.d.cts.map +1 -0
- package/dist/CacheItem.d.mts.map +1 -1
- package/dist/CacheItem.mjs +11 -8
- package/dist/CacheItem.mjs.map +1 -1
- package/dist/{ParentCache.js → ParentCache.cjs} +4 -3
- package/dist/{ParentCache.d.ts → ParentCache.d.cts} +4 -4
- package/dist/ParentCache.d.cts.map +1 -0
- package/dist/ParentCache.d.mts +3 -3
- package/dist/ParentCache.d.mts.map +1 -1
- package/dist/ParentCache.mjs +3 -2
- package/dist/ParentCache.mjs.map +1 -1
- package/dist/{index.js → index.cjs} +14 -10
- package/dist/{index.d.ts → index.d.cts} +10 -8
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -1
- package/dist/{useCachedResponsivePrecommitValue.js → useCachedResponsivePrecommitValue.cjs} +15 -9
- package/dist/{useCachedResponsivePrecommitValue.d.ts → useCachedResponsivePrecommitValue.d.cts} +2 -3
- package/dist/useCachedResponsivePrecommitValue.d.cts.map +1 -0
- package/dist/useCachedResponsivePrecommitValue.d.mts +0 -1
- package/dist/useCachedResponsivePrecommitValue.d.mts.map +1 -1
- package/dist/useCachedResponsivePrecommitValue.mjs +13 -7
- package/dist/useCachedResponsivePrecommitValue.mjs.map +1 -1
- package/dist/{useDisposableState.js → useDisposableState.cjs} +9 -10
- package/dist/{useDisposableState.d.ts → useDisposableState.d.cts} +3 -3
- package/dist/useDisposableState.d.cts.map +1 -0
- package/dist/useDisposableState.d.mts.map +1 -1
- package/dist/useDisposableState.mjs +7 -6
- package/dist/useDisposableState.mjs.map +1 -1
- package/dist/useEffectsRerunWithoutRender.cjs +27 -0
- package/dist/useEffectsRerunWithoutRender.d.cts +19 -0
- package/dist/useEffectsRerunWithoutRender.d.cts.map +1 -0
- package/dist/useEffectsRerunWithoutRender.d.mts +19 -0
- package/dist/useEffectsRerunWithoutRender.d.mts.map +1 -0
- package/dist/useEffectsRerunWithoutRender.mjs +28 -0
- package/dist/useEffectsRerunWithoutRender.mjs.map +1 -0
- package/dist/{useHasCommittedRef.js → useHasCommittedRef.cjs} +0 -2
- package/dist/{useHasCommittedRef.d.ts → useHasCommittedRef.d.cts} +1 -2
- package/dist/useHasCommittedRef.d.cts.map +1 -0
- package/dist/useHasCommittedRef.d.mts +0 -1
- package/dist/useHasCommittedRef.d.mts.map +1 -1
- package/dist/{useLazyDisposableState.js → useLazyDisposableState.cjs} +6 -6
- package/dist/{useLazyDisposableState.d.ts → useLazyDisposableState.d.cts} +3 -4
- package/dist/useLazyDisposableState.d.cts.map +1 -0
- package/dist/useLazyDisposableState.d.mts +0 -1
- package/dist/useLazyDisposableState.d.mts.map +1 -1
- package/dist/useLazyDisposableState.mjs +3 -3
- package/dist/useLazyDisposableState.mjs.map +1 -1
- package/dist/useUpdatableDisposableClearableState.cjs +36 -0
- package/dist/useUpdatableDisposableClearableState.d.cts +26 -0
- package/dist/useUpdatableDisposableClearableState.d.cts.map +1 -0
- package/dist/useUpdatableDisposableClearableState.d.mts +26 -0
- package/dist/useUpdatableDisposableClearableState.d.mts.map +1 -0
- package/dist/useUpdatableDisposableClearableState.mjs +37 -0
- package/dist/useUpdatableDisposableClearableState.mjs.map +1 -0
- package/dist/{useUpdatableDisposableState.js → useUpdatableDisposableState.cjs} +6 -4
- package/dist/{useUpdatableDisposableState.d.ts → useUpdatableDisposableState.d.cts} +1 -1
- package/dist/useUpdatableDisposableState.d.cts.map +1 -0
- package/dist/useUpdatableDisposableState.d.mts.map +1 -1
- package/dist/useUpdatableDisposableState.mjs +5 -1
- package/dist/useUpdatableDisposableState.mjs.map +1 -1
- package/package.json +9 -6
- package/src/CacheItem.test.ts +40 -2
- package/src/CacheItem.ts +1 -0
- package/src/ParentCache.ts +26 -21
- package/src/index.ts +2 -0
- package/src/useCachedResponsivePrecommitValue.test.tsx +8 -3
- package/src/useCachedResponsivePrecommitValue.ts +32 -20
- package/src/useDisposableState.ts +13 -15
- package/src/useEffectsRerunWithoutRender.test.tsx +54 -0
- package/src/useEffectsRerunWithoutRender.ts +23 -0
- package/src/useLazyDisposableState.test.tsx +73 -34
- package/src/useLazyDisposableState.ts +4 -5
- package/src/useUpdatableDisposableClearableState.ts +67 -0
- package/src/useUpdatableDisposableState.test.tsx +3 -2
- package/src/useUpdatableDisposableState.ts +2 -0
- package/tsconfig.json +2 -4
- package/vitest.config.ts +8 -0
- package/dist/CacheItem.d.ts.map +0 -1
- package/dist/ParentCache.d.ts.map +0 -1
- package/dist/_virtual/rolldown_runtime.js +0 -25
- package/dist/useCachedResponsivePrecommitValue.d.ts.map +0 -1
- package/dist/useDisposableState.d.ts.map +0 -1
- package/dist/useHasCommittedRef.d.ts.map +0 -1
- package/dist/useLazyDisposableState.d.ts.map +0 -1
- package/dist/useUpdatableDisposableState.d.ts.map +0 -1
- package/tsconfig.pkg.json +0 -9
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const require_useUpdatableDisposableState = require('./useUpdatableDisposableState.js');
|
|
1
|
+
const require_useCachedResponsivePrecommitValue = require('./useCachedResponsivePrecommitValue.cjs');
|
|
2
|
+
const require_useUpdatableDisposableState = require('./useUpdatableDisposableState.cjs');
|
|
4
3
|
let react = require("react");
|
|
5
|
-
react = require_rolldown_runtime.__toESM(react);
|
|
6
4
|
|
|
7
5
|
//#region src/useDisposableState.ts
|
|
8
6
|
function useDisposableState(parentCache) {
|
|
9
7
|
const itemCleanupPairRef = (0, react.useRef)(null);
|
|
10
8
|
const preCommitItem = require_useCachedResponsivePrecommitValue.useCachedResponsivePrecommitValue(parentCache, (pair) => {
|
|
11
|
-
itemCleanupPairRef.current?.[1]();
|
|
12
9
|
itemCleanupPairRef.current = pair;
|
|
13
10
|
});
|
|
14
11
|
const { state: stateFromDisposableStateHook, setState } = require_useUpdatableDisposableState.useUpdatableDisposableState();
|
|
15
12
|
(0, react.useEffect)(function cleanupItemCleanupPairRefAfterSetState() {
|
|
16
|
-
if (stateFromDisposableStateHook !== require_useUpdatableDisposableState.UNASSIGNED_STATE)
|
|
17
|
-
itemCleanupPairRef.current
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
if (stateFromDisposableStateHook !== require_useUpdatableDisposableState.UNASSIGNED_STATE) {
|
|
14
|
+
if (itemCleanupPairRef.current != null) {
|
|
15
|
+
itemCleanupPairRef.current[1]();
|
|
16
|
+
itemCleanupPairRef.current = null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
20
19
|
}, [stateFromDisposableStateHook]);
|
|
21
20
|
(0, react.useEffect)(function cleanupItemCleanupPairRefIfSetStateNotCalled() {
|
|
22
21
|
return () => {
|
|
@@ -25,7 +24,7 @@ function useDisposableState(parentCache) {
|
|
|
25
24
|
itemCleanupPairRef.current = null;
|
|
26
25
|
}
|
|
27
26
|
};
|
|
28
|
-
}, []);
|
|
27
|
+
}, [parentCache]);
|
|
29
28
|
const state = (stateFromDisposableStateHook !== require_useUpdatableDisposableState.UNASSIGNED_STATE ? stateFromDisposableStateHook : null) ?? preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
|
|
30
29
|
if (state != null) return {
|
|
31
30
|
state,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ParentCache } from "./ParentCache.
|
|
2
|
-
import { UnassignedState } from "./useUpdatableDisposableState.
|
|
1
|
+
import { ParentCache } from "./ParentCache.cjs";
|
|
2
|
+
import { UnassignedState } from "./useUpdatableDisposableState.cjs";
|
|
3
3
|
import { ItemCleanupPair } from "@isograph/disposable-types";
|
|
4
4
|
|
|
5
5
|
//#region src/useDisposableState.d.ts
|
|
@@ -10,4 +10,4 @@ type UseUpdatableDisposableStateReturnValue<T> = {
|
|
|
10
10
|
declare function useDisposableState<T = never>(parentCache: ParentCache<T>): UseUpdatableDisposableStateReturnValue<T>;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { useDisposableState };
|
|
13
|
-
//# sourceMappingURL=useDisposableState.d.
|
|
13
|
+
//# sourceMappingURL=useDisposableState.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDisposableState.d.cts","names":[],"sources":["../src/useDisposableState.ts"],"mappings":";;;;;KAUK,sCAAA;EACH,KAAA,EAAO,CAAA;EACP,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;AAAA;AAAA,iBAG9B,kBAAA,WAAA,CACd,WAAA,EAAa,WAAA,CAAY,CAAA,IACxB,sCAAA,CAAuC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDisposableState.d.mts","names":[],"sources":["../src/useDisposableState.ts"],"
|
|
1
|
+
{"version":3,"file":"useDisposableState.d.mts","names":[],"sources":["../src/useDisposableState.ts"],"mappings":";;;;;KAUK,sCAAA;EACH,KAAA,EAAO,CAAA;EACP,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;AAAA;AAAA,iBAG9B,kBAAA,WAAA,CACd,WAAA,EAAa,WAAA,CAAY,CAAA,IACxB,sCAAA,CAAuC,CAAA"}
|
|
@@ -6,15 +6,16 @@ import { useEffect, useRef } from "react";
|
|
|
6
6
|
function useDisposableState(parentCache) {
|
|
7
7
|
const itemCleanupPairRef = useRef(null);
|
|
8
8
|
const preCommitItem = useCachedResponsivePrecommitValue(parentCache, (pair) => {
|
|
9
|
-
itemCleanupPairRef.current?.[1]();
|
|
10
9
|
itemCleanupPairRef.current = pair;
|
|
11
10
|
});
|
|
12
11
|
const { state: stateFromDisposableStateHook, setState } = useUpdatableDisposableState();
|
|
13
12
|
useEffect(function cleanupItemCleanupPairRefAfterSetState() {
|
|
14
|
-
if (stateFromDisposableStateHook !== UNASSIGNED_STATE)
|
|
15
|
-
itemCleanupPairRef.current
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (stateFromDisposableStateHook !== UNASSIGNED_STATE) {
|
|
14
|
+
if (itemCleanupPairRef.current != null) {
|
|
15
|
+
itemCleanupPairRef.current[1]();
|
|
16
|
+
itemCleanupPairRef.current = null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
18
19
|
}, [stateFromDisposableStateHook]);
|
|
19
20
|
useEffect(function cleanupItemCleanupPairRefIfSetStateNotCalled() {
|
|
20
21
|
return () => {
|
|
@@ -23,7 +24,7 @@ function useDisposableState(parentCache) {
|
|
|
23
24
|
itemCleanupPairRef.current = null;
|
|
24
25
|
}
|
|
25
26
|
};
|
|
26
|
-
}, []);
|
|
27
|
+
}, [parentCache]);
|
|
27
28
|
const state = (stateFromDisposableStateHook !== UNASSIGNED_STATE ? stateFromDisposableStateHook : null) ?? preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
|
|
28
29
|
if (state != null) return {
|
|
29
30
|
state,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDisposableState.mjs","names":[
|
|
1
|
+
{"version":3,"file":"useDisposableState.mjs","names":[],"sources":["../src/useDisposableState.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport { useEffect, useRef } from 'react';\nimport type { ParentCache } from './ParentCache';\nimport { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';\nimport {\n UNASSIGNED_STATE,\n type UnassignedState,\n useUpdatableDisposableState,\n} from './useUpdatableDisposableState';\n\ntype UseUpdatableDisposableStateReturnValue<T> = {\n state: T;\n setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;\n};\n\nexport function useDisposableState<T = never>(\n parentCache: ParentCache<T>,\n): UseUpdatableDisposableStateReturnValue<T> {\n const itemCleanupPairRef = useRef<ItemCleanupPair<T> | null>(null);\n\n const preCommitItem = useCachedResponsivePrecommitValue(\n parentCache,\n (pair) => {\n itemCleanupPairRef.current = pair;\n },\n );\n\n const { state: stateFromDisposableStateHook, setState } =\n useUpdatableDisposableState<T>();\n\n useEffect(\n function cleanupItemCleanupPairRefAfterSetState() {\n if (stateFromDisposableStateHook !== UNASSIGNED_STATE) {\n if (itemCleanupPairRef.current != null) {\n itemCleanupPairRef.current[1]();\n itemCleanupPairRef.current = null;\n }\n }\n },\n [stateFromDisposableStateHook],\n );\n\n useEffect(\n function cleanupItemCleanupPairRefIfSetStateNotCalled() {\n return () => {\n if (itemCleanupPairRef.current != null) {\n itemCleanupPairRef.current[1]();\n // Forgotten so that nothing can release this pair a second time\n // before an effect re-run (StrictMode, Fast Refresh) stores a new one.\n itemCleanupPairRef.current = null;\n }\n };\n },\n [parentCache],\n );\n const state: T | undefined =\n (stateFromDisposableStateHook !== UNASSIGNED_STATE\n ? stateFromDisposableStateHook\n : null) ??\n preCommitItem?.state ??\n itemCleanupPairRef.current?.[0];\n\n if (state != null) {\n return {\n state: state,\n setState,\n };\n }\n // Safety: we can be in one of three states. Pre-commit, in which case\n // preCommitItem is assigned, post-commit but before setState has been\n // called, in which case itemCleanupPairRef.current is assigned, or\n // after setState has been called, in which case\n // stateFromDisposableStateHook is assigned.\n //\n // Therefore, the type of state is T, not T | undefined. But the fact\n // that we are in one of the three states is not reflected in the types.\n // So we have to cast to T.\n //\n // Note that in the post-commit post-setState state, itemCleanupPairRef\n // can still be assigned, during the render before the\n // cleanupItemCleanupPairRefAfterSetState effect is called.\n throw new Error(\n 'state was unexpectedly null. This indicates a bug in react-disposable-state.',\n );\n}\n\n// @ts-ignore\nfunction tsTests() {\n let x: any;\n const a = useDisposableState(x);\n // This should be a compiler error, because the generic is inferred to be of\n // type never. TODO determine why this doesn't break the build!\n // @ts-expect-error\n a.setState(['asdf', () => {}]);\n // @ts-expect-error\n a.setState([UNASSIGNED_STATE, () => {}]);\n const b = useDisposableState<string | UnassignedState>(x);\n // @ts-expect-error\n b.setState([UNASSIGNED_STATE, () => {}]);\n b.setState(['asdf', () => {}]);\n}\n"],"mappings":";;;;;AAeA,SAAgB,mBACd,aAC2C;CAC3C,MAAM,qBAAqB,OAAkC,KAAK;CAElE,MAAM,gBAAgB,kCACpB,cACC,SAAS;AACR,qBAAmB,UAAU;GAEhC;CAED,MAAM,EAAE,OAAO,8BAA8B,aAC3C,6BAAgC;AAElC,WACE,SAAS,yCAAyC;AAChD,MAAI,iCAAiC,kBACnC;OAAI,mBAAmB,WAAW,MAAM;AACtC,uBAAmB,QAAQ,IAAI;AAC/B,uBAAmB,UAAU;;;IAInC,CAAC,6BAA6B,CAC/B;AAED,WACE,SAAS,+CAA+C;AACtD,eAAa;AACX,OAAI,mBAAmB,WAAW,MAAM;AACtC,uBAAmB,QAAQ,IAAI;AAG/B,uBAAmB,UAAU;;;IAInC,CAAC,YAAY,CACd;CACD,MAAM,SACH,iCAAiC,mBAC9B,+BACA,SACJ,eAAe,SACf,mBAAmB,UAAU;AAE/B,KAAI,SAAS,KACX,QAAO;EACE;EACP;EACD;AAeH,OAAM,IAAI,MACR,+EACD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
|
|
3
|
+
//#region src/useEffectsRerunWithoutRender.ts
|
|
4
|
+
/**
|
|
5
|
+
* Detects that React is running this component's effects again without a
|
|
6
|
+
* render in between. That happens on StrictMode's simulated unmount and
|
|
7
|
+
* remount on the first commit, on Fast Refresh, and when an `Activity`
|
|
8
|
+
* boundary hides and then shows the component. In each case React runs every
|
|
9
|
+
* effect's cleanup and then its mount, so a cleanup that sets a flag is
|
|
10
|
+
* observable from the mounts that follow.
|
|
11
|
+
*
|
|
12
|
+
* Returns a ref whose `current` is `true` from the moment the cleanup ran until
|
|
13
|
+
* the caller resets it. The effect that must tell a re-run apart from a first
|
|
14
|
+
* mount reads it and sets it back to `false`; nothing else clears it.
|
|
15
|
+
*/
|
|
16
|
+
function useEffectsRerunWithoutRenderRef() {
|
|
17
|
+
const effectsRerunWithoutRenderRef = (0, react.useRef)(false);
|
|
18
|
+
(0, react.useEffect)(() => {
|
|
19
|
+
return () => {
|
|
20
|
+
effectsRerunWithoutRenderRef.current = true;
|
|
21
|
+
};
|
|
22
|
+
}, []);
|
|
23
|
+
return effectsRerunWithoutRenderRef;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.useEffectsRerunWithoutRenderRef = useEffectsRerunWithoutRenderRef;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/useEffectsRerunWithoutRender.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Detects that React is running this component's effects again without a
|
|
6
|
+
* render in between. That happens on StrictMode's simulated unmount and
|
|
7
|
+
* remount on the first commit, on Fast Refresh, and when an `Activity`
|
|
8
|
+
* boundary hides and then shows the component. In each case React runs every
|
|
9
|
+
* effect's cleanup and then its mount, so a cleanup that sets a flag is
|
|
10
|
+
* observable from the mounts that follow.
|
|
11
|
+
*
|
|
12
|
+
* Returns a ref whose `current` is `true` from the moment the cleanup ran until
|
|
13
|
+
* the caller resets it. The effect that must tell a re-run apart from a first
|
|
14
|
+
* mount reads it and sets it back to `false`; nothing else clears it.
|
|
15
|
+
*/
|
|
16
|
+
declare function useEffectsRerunWithoutRenderRef(): MutableRefObject<boolean>;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useEffectsRerunWithoutRenderRef };
|
|
19
|
+
//# sourceMappingURL=useEffectsRerunWithoutRender.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectsRerunWithoutRender.d.cts","names":[],"sources":["../src/useEffectsRerunWithoutRender.ts"],"mappings":";;;;;AAcA;;;;;;;;;;iBAAgB,+BAAA,CAAA,GAAmC,gBAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/useEffectsRerunWithoutRender.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Detects that React is running this component's effects again without a
|
|
6
|
+
* render in between. That happens on StrictMode's simulated unmount and
|
|
7
|
+
* remount on the first commit, on Fast Refresh, and when an `Activity`
|
|
8
|
+
* boundary hides and then shows the component. In each case React runs every
|
|
9
|
+
* effect's cleanup and then its mount, so a cleanup that sets a flag is
|
|
10
|
+
* observable from the mounts that follow.
|
|
11
|
+
*
|
|
12
|
+
* Returns a ref whose `current` is `true` from the moment the cleanup ran until
|
|
13
|
+
* the caller resets it. The effect that must tell a re-run apart from a first
|
|
14
|
+
* mount reads it and sets it back to `false`; nothing else clears it.
|
|
15
|
+
*/
|
|
16
|
+
declare function useEffectsRerunWithoutRenderRef(): MutableRefObject<boolean>;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useEffectsRerunWithoutRenderRef };
|
|
19
|
+
//# sourceMappingURL=useEffectsRerunWithoutRender.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectsRerunWithoutRender.d.mts","names":[],"sources":["../src/useEffectsRerunWithoutRender.ts"],"mappings":";;;;;AAcA;;;;;;;;;;iBAAgB,+BAAA,CAAA,GAAmC,gBAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/useEffectsRerunWithoutRender.ts
|
|
4
|
+
/**
|
|
5
|
+
* Detects that React is running this component's effects again without a
|
|
6
|
+
* render in between. That happens on StrictMode's simulated unmount and
|
|
7
|
+
* remount on the first commit, on Fast Refresh, and when an `Activity`
|
|
8
|
+
* boundary hides and then shows the component. In each case React runs every
|
|
9
|
+
* effect's cleanup and then its mount, so a cleanup that sets a flag is
|
|
10
|
+
* observable from the mounts that follow.
|
|
11
|
+
*
|
|
12
|
+
* Returns a ref whose `current` is `true` from the moment the cleanup ran until
|
|
13
|
+
* the caller resets it. The effect that must tell a re-run apart from a first
|
|
14
|
+
* mount reads it and sets it back to `false`; nothing else clears it.
|
|
15
|
+
*/
|
|
16
|
+
function useEffectsRerunWithoutRenderRef() {
|
|
17
|
+
const effectsRerunWithoutRenderRef = useRef(false);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
return () => {
|
|
20
|
+
effectsRerunWithoutRenderRef.current = true;
|
|
21
|
+
};
|
|
22
|
+
}, []);
|
|
23
|
+
return effectsRerunWithoutRenderRef;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { useEffectsRerunWithoutRenderRef };
|
|
28
|
+
//# sourceMappingURL=useEffectsRerunWithoutRender.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectsRerunWithoutRender.mjs","names":[],"sources":["../src/useEffectsRerunWithoutRender.ts"],"sourcesContent":["import { type MutableRefObject, useEffect, useRef } from 'react';\n\n/**\n * Detects that React is running this component's effects again without a\n * render in between. That happens on StrictMode's simulated unmount and\n * remount on the first commit, on Fast Refresh, and when an `Activity`\n * boundary hides and then shows the component. In each case React runs every\n * effect's cleanup and then its mount, so a cleanup that sets a flag is\n * observable from the mounts that follow.\n *\n * Returns a ref whose `current` is `true` from the moment the cleanup ran until\n * the caller resets it. The effect that must tell a re-run apart from a first\n * mount reads it and sets it back to `false`; nothing else clears it.\n */\nexport function useEffectsRerunWithoutRenderRef(): MutableRefObject<boolean> {\n const effectsRerunWithoutRenderRef = useRef(false);\n useEffect(() => {\n return () => {\n effectsRerunWithoutRenderRef.current = true;\n };\n }, []);\n return effectsRerunWithoutRenderRef;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,kCAA6D;CAC3E,MAAM,+BAA+B,OAAO,MAAM;AAClD,iBAAgB;AACd,eAAa;AACX,gCAA6B,UAAU;;IAExC,EAAE,CAAC;AACN,QAAO"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { MutableRefObject } from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/useHasCommittedRef.d.ts
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Returns true if the component has committed, false otherwise.
|
|
7
6
|
*/
|
|
8
7
|
declare function useHasCommittedRef(): MutableRefObject<boolean>;
|
|
9
8
|
//#endregion
|
|
10
9
|
export { useHasCommittedRef };
|
|
11
|
-
//# sourceMappingURL=useHasCommittedRef.d.
|
|
10
|
+
//# sourceMappingURL=useHasCommittedRef.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHasCommittedRef.d.cts","names":[],"sources":["../src/useHasCommittedRef.ts"],"mappings":";;;;;AAKA;iBAAgB,kBAAA,CAAA,GAAsB,gBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHasCommittedRef.d.mts","names":[],"sources":["../src/useHasCommittedRef.ts"],"
|
|
1
|
+
{"version":3,"file":"useHasCommittedRef.d.mts","names":[],"sources":["../src/useHasCommittedRef.ts"],"mappings":";;;;;AAKA;iBAAgB,kBAAA,CAAA,GAAsB,gBAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const require_useCachedResponsivePrecommitValue = require('./useCachedResponsivePrecommitValue.cjs');
|
|
3
4
|
let react = require("react");
|
|
4
|
-
react = require_rolldown_runtime.__toESM(react);
|
|
5
5
|
|
|
6
6
|
//#region src/useLazyDisposableState.ts
|
|
7
7
|
/**
|
|
@@ -16,16 +16,16 @@ react = require_rolldown_runtime.__toESM(react);
|
|
|
16
16
|
function useLazyDisposableState(parentCache) {
|
|
17
17
|
const itemCleanupPairRef = (0, react.useRef)(null);
|
|
18
18
|
const preCommitItem = require_useCachedResponsivePrecommitValue.useCachedResponsivePrecommitValue(parentCache, (pair) => {
|
|
19
|
-
itemCleanupPairRef.current?.[1]();
|
|
20
19
|
itemCleanupPairRef.current = pair;
|
|
21
20
|
});
|
|
22
21
|
(0, react.useEffect)(() => {
|
|
23
22
|
return () => {
|
|
24
23
|
const cleanupFn = itemCleanupPairRef.current?.[1];
|
|
25
24
|
if (cleanupFn == null) throw new Error("cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.");
|
|
26
|
-
|
|
25
|
+
cleanupFn();
|
|
26
|
+
itemCleanupPairRef.current = null;
|
|
27
27
|
};
|
|
28
|
-
}, []);
|
|
28
|
+
}, [parentCache]);
|
|
29
29
|
const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
|
|
30
30
|
if (returnedItem != null) return { state: returnedItem };
|
|
31
31
|
throw new Error("returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.");
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { ParentCache } from "./ParentCache.
|
|
2
|
-
import { UnassignedState } from "./useUpdatableDisposableState.
|
|
1
|
+
import { ParentCache } from "./ParentCache.cjs";
|
|
2
|
+
import { UnassignedState } from "./useUpdatableDisposableState.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/useLazyDisposableState.d.ts
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* useLazyDisposableState<T>
|
|
8
7
|
* - Takes a mutable parent cache and a factory function
|
|
@@ -17,4 +16,4 @@ declare function useLazyDisposableState<T>(parentCache: ParentCache<Exclude<T, U
|
|
|
17
16
|
};
|
|
18
17
|
//#endregion
|
|
19
18
|
export { useLazyDisposableState };
|
|
20
|
-
//# sourceMappingURL=useLazyDisposableState.d.
|
|
19
|
+
//# sourceMappingURL=useLazyDisposableState.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLazyDisposableState.d.cts","names":[],"sources":["../src/useLazyDisposableState.ts"],"mappings":";;;;;;AAiBA;;;;;;;iBAAgB,sBAAA,GAAA,CACd,WAAA,EAAa,WAAA,CAAY,OAAA,CAAQ,CAAA,EAAG,eAAA;EAEpC,KAAA,EAAO,CAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLazyDisposableState.d.mts","names":[],"sources":["../src/useLazyDisposableState.ts"],"
|
|
1
|
+
{"version":3,"file":"useLazyDisposableState.d.mts","names":[],"sources":["../src/useLazyDisposableState.ts"],"mappings":";;;;;;AAiBA;;;;;;;iBAAgB,sBAAA,GAAA,CACd,WAAA,EAAa,WAAA,CAAY,OAAA,CAAQ,CAAA,EAAG,eAAA;EAEpC,KAAA,EAAO,CAAA;AAAA"}
|
|
@@ -14,16 +14,16 @@ import { useEffect, useRef } from "react";
|
|
|
14
14
|
function useLazyDisposableState(parentCache) {
|
|
15
15
|
const itemCleanupPairRef = useRef(null);
|
|
16
16
|
const preCommitItem = useCachedResponsivePrecommitValue(parentCache, (pair) => {
|
|
17
|
-
itemCleanupPairRef.current?.[1]();
|
|
18
17
|
itemCleanupPairRef.current = pair;
|
|
19
18
|
});
|
|
20
19
|
useEffect(() => {
|
|
21
20
|
return () => {
|
|
22
21
|
const cleanupFn = itemCleanupPairRef.current?.[1];
|
|
23
22
|
if (cleanupFn == null) throw new Error("cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.");
|
|
24
|
-
|
|
23
|
+
cleanupFn();
|
|
24
|
+
itemCleanupPairRef.current = null;
|
|
25
25
|
};
|
|
26
|
-
}, []);
|
|
26
|
+
}, [parentCache]);
|
|
27
27
|
const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];
|
|
28
28
|
if (returnedItem != null) return { state: returnedItem };
|
|
29
29
|
throw new Error("returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLazyDisposableState.mjs","names":[],"sources":["../src/useLazyDisposableState.ts"],"sourcesContent":["'use strict';\n\nimport type { ItemCleanupPair } from '@isograph/
|
|
1
|
+
{"version":3,"file":"useLazyDisposableState.mjs","names":[],"sources":["../src/useLazyDisposableState.ts"],"sourcesContent":["'use strict';\n\nimport type { ItemCleanupPair } from '@isograph/disposable-types';\nimport { useEffect, useRef } from 'react';\nimport type { ParentCache } from './ParentCache';\nimport { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';\nimport { type UnassignedState } from './useUpdatableDisposableState';\n\n/**\n * useLazyDisposableState<T>\n * - Takes a mutable parent cache and a factory function\n * - Returns { state: T }\n *\n * This lazily loads the disposable item using useCachedResponsivePrecommitValue, then\n * (on commit) sets it in state. The item continues to be returned after\n * commit and is disposed when the hook unmounts.\n */\nexport function useLazyDisposableState<T>(\n parentCache: ParentCache<Exclude<T, UnassignedState>>,\n): {\n state: T;\n} {\n const itemCleanupPairRef = useRef<ItemCleanupPair<T> | null>(null);\n const preCommitItem = useCachedResponsivePrecommitValue(\n parentCache,\n (pair) => {\n itemCleanupPairRef.current = pair;\n },\n );\n\n useEffect(() => {\n return () => {\n const cleanupFn = itemCleanupPairRef.current?.[1];\n // TODO confirm useEffect is called in order.\n if (cleanupFn == null) {\n throw new Error(\n 'cleanupFn unexpectedly null. This indicates a bug in react-disposable-state.',\n );\n }\n cleanupFn();\n itemCleanupPairRef.current = null;\n };\n }, [parentCache]);\n\n const returnedItem = preCommitItem?.state ?? itemCleanupPairRef.current?.[0];\n\n if (returnedItem != null) {\n return { state: returnedItem };\n }\n\n // Safety: This can't happen. For renders before the initial commit, preCommitItem\n // is non-null. During the initial commit, we assign itemCleanupPairRef.current,\n // so during subsequent renders, itemCleanupPairRef.current is non-null.\n throw new Error(\n 'returnedItem was unexpectedly null. This indicates a bug in react-disposable-state.',\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,uBACd,aAGA;CACA,MAAM,qBAAqB,OAAkC,KAAK;CAClE,MAAM,gBAAgB,kCACpB,cACC,SAAS;AACR,qBAAmB,UAAU;GAEhC;AAED,iBAAgB;AACd,eAAa;GACX,MAAM,YAAY,mBAAmB,UAAU;AAE/C,OAAI,aAAa,KACf,OAAM,IAAI,MACR,+EACD;AAEH,cAAW;AACX,sBAAmB,UAAU;;IAE9B,CAAC,YAAY,CAAC;CAEjB,MAAM,eAAe,eAAe,SAAS,mBAAmB,UAAU;AAE1E,KAAI,gBAAgB,KAClB,QAAO,EAAE,OAAO,cAAc;AAMhC,OAAM,IAAI,MACR,sFACD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const require_useUpdatableDisposableState = require('./useUpdatableDisposableState.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
|
|
4
|
+
//#region src/useUpdatableDisposableClearableState.ts
|
|
5
|
+
/**
|
|
6
|
+
* The item that `clearState` puts in the underlying state. It is never returned
|
|
7
|
+
* from this hook; the hook reports UNASSIGNED_STATE while it is current.
|
|
8
|
+
*/
|
|
9
|
+
const CLEARED_STATE = Symbol();
|
|
10
|
+
function noop() {}
|
|
11
|
+
/**
|
|
12
|
+
* useUpdatableDisposableClearableState
|
|
13
|
+
* - useUpdatableDisposableState, plus clearState.
|
|
14
|
+
* - clearState returns the state to UNASSIGNED_STATE. The item that was in state
|
|
15
|
+
* is disposed on the next commit, exactly as if it had been superseded by
|
|
16
|
+
* setState.
|
|
17
|
+
* - Like setState, clearState throws if called before the initial commit.
|
|
18
|
+
*
|
|
19
|
+
* This is a wrapper around useUpdatableDisposableState: clearing sets a sentinel
|
|
20
|
+
* item with no cleanup, so the underlying hook's commit-time disposal of
|
|
21
|
+
* superseded items disposes the cleared item, and the sentinel is mapped back to
|
|
22
|
+
* UNASSIGNED_STATE on the way out.
|
|
23
|
+
*/
|
|
24
|
+
function useUpdatableDisposableClearableState() {
|
|
25
|
+
const { state, setState } = require_useUpdatableDisposableState.useUpdatableDisposableState();
|
|
26
|
+
return {
|
|
27
|
+
clearState: (0, react.useCallback)(() => {
|
|
28
|
+
setState([CLEARED_STATE, noop]);
|
|
29
|
+
}, [setState]),
|
|
30
|
+
setState,
|
|
31
|
+
state: state === CLEARED_STATE ? require_useUpdatableDisposableState.UNASSIGNED_STATE : state
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.useUpdatableDisposableClearableState = useUpdatableDisposableClearableState;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UnassignedState } from "./useUpdatableDisposableState.cjs";
|
|
2
|
+
import { ItemCleanupPair } from "@isograph/disposable-types";
|
|
3
|
+
|
|
4
|
+
//#region src/useUpdatableDisposableClearableState.d.ts
|
|
5
|
+
type UseUpdatableDisposableClearableStateReturnValue<T> = {
|
|
6
|
+
state: T | UnassignedState;
|
|
7
|
+
setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;
|
|
8
|
+
clearState: () => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* useUpdatableDisposableClearableState
|
|
12
|
+
* - useUpdatableDisposableState, plus clearState.
|
|
13
|
+
* - clearState returns the state to UNASSIGNED_STATE. The item that was in state
|
|
14
|
+
* is disposed on the next commit, exactly as if it had been superseded by
|
|
15
|
+
* setState.
|
|
16
|
+
* - Like setState, clearState throws if called before the initial commit.
|
|
17
|
+
*
|
|
18
|
+
* This is a wrapper around useUpdatableDisposableState: clearing sets a sentinel
|
|
19
|
+
* item with no cleanup, so the underlying hook's commit-time disposal of
|
|
20
|
+
* superseded items disposes the cleared item, and the sentinel is mapped back to
|
|
21
|
+
* UNASSIGNED_STATE on the way out.
|
|
22
|
+
*/
|
|
23
|
+
declare function useUpdatableDisposableClearableState<T = never>(): UseUpdatableDisposableClearableStateReturnValue<T>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { useUpdatableDisposableClearableState };
|
|
26
|
+
//# sourceMappingURL=useUpdatableDisposableClearableState.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableClearableState.d.cts","names":[],"sources":["../src/useUpdatableDisposableClearableState.ts"],"mappings":";;;;KAQK,+CAAA;EACH,KAAA,EAAO,CAAA,GAAI,eAAA;EACX,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;EAC5C,UAAA;AAAA;;;;;;;;;;;;;;iBAyBc,oCAAA,WAAA,CAAA,GAEX,+CAAA,CAAgD,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UnassignedState } from "./useUpdatableDisposableState.mjs";
|
|
2
|
+
import { ItemCleanupPair } from "@isograph/disposable-types";
|
|
3
|
+
|
|
4
|
+
//#region src/useUpdatableDisposableClearableState.d.ts
|
|
5
|
+
type UseUpdatableDisposableClearableStateReturnValue<T> = {
|
|
6
|
+
state: T | UnassignedState;
|
|
7
|
+
setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;
|
|
8
|
+
clearState: () => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* useUpdatableDisposableClearableState
|
|
12
|
+
* - useUpdatableDisposableState, plus clearState.
|
|
13
|
+
* - clearState returns the state to UNASSIGNED_STATE. The item that was in state
|
|
14
|
+
* is disposed on the next commit, exactly as if it had been superseded by
|
|
15
|
+
* setState.
|
|
16
|
+
* - Like setState, clearState throws if called before the initial commit.
|
|
17
|
+
*
|
|
18
|
+
* This is a wrapper around useUpdatableDisposableState: clearing sets a sentinel
|
|
19
|
+
* item with no cleanup, so the underlying hook's commit-time disposal of
|
|
20
|
+
* superseded items disposes the cleared item, and the sentinel is mapped back to
|
|
21
|
+
* UNASSIGNED_STATE on the way out.
|
|
22
|
+
*/
|
|
23
|
+
declare function useUpdatableDisposableClearableState<T = never>(): UseUpdatableDisposableClearableStateReturnValue<T>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { useUpdatableDisposableClearableState };
|
|
26
|
+
//# sourceMappingURL=useUpdatableDisposableClearableState.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableClearableState.d.mts","names":[],"sources":["../src/useUpdatableDisposableClearableState.ts"],"mappings":";;;;KAQK,+CAAA;EACH,KAAA,EAAO,CAAA,GAAI,eAAA;EACX,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;EAC5C,UAAA;AAAA;;;;;;;;;;;;;;iBAyBc,oCAAA,WAAA,CAAA,GAEX,+CAAA,CAAgD,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { UNASSIGNED_STATE, useUpdatableDisposableState } from "./useUpdatableDisposableState.mjs";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/useUpdatableDisposableClearableState.ts
|
|
5
|
+
/**
|
|
6
|
+
* The item that `clearState` puts in the underlying state. It is never returned
|
|
7
|
+
* from this hook; the hook reports UNASSIGNED_STATE while it is current.
|
|
8
|
+
*/
|
|
9
|
+
const CLEARED_STATE = Symbol();
|
|
10
|
+
function noop() {}
|
|
11
|
+
/**
|
|
12
|
+
* useUpdatableDisposableClearableState
|
|
13
|
+
* - useUpdatableDisposableState, plus clearState.
|
|
14
|
+
* - clearState returns the state to UNASSIGNED_STATE. The item that was in state
|
|
15
|
+
* is disposed on the next commit, exactly as if it had been superseded by
|
|
16
|
+
* setState.
|
|
17
|
+
* - Like setState, clearState throws if called before the initial commit.
|
|
18
|
+
*
|
|
19
|
+
* This is a wrapper around useUpdatableDisposableState: clearing sets a sentinel
|
|
20
|
+
* item with no cleanup, so the underlying hook's commit-time disposal of
|
|
21
|
+
* superseded items disposes the cleared item, and the sentinel is mapped back to
|
|
22
|
+
* UNASSIGNED_STATE on the way out.
|
|
23
|
+
*/
|
|
24
|
+
function useUpdatableDisposableClearableState() {
|
|
25
|
+
const { state, setState } = useUpdatableDisposableState();
|
|
26
|
+
return {
|
|
27
|
+
clearState: useCallback(() => {
|
|
28
|
+
setState([CLEARED_STATE, noop]);
|
|
29
|
+
}, [setState]),
|
|
30
|
+
setState,
|
|
31
|
+
state: state === CLEARED_STATE ? UNASSIGNED_STATE : state
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { useUpdatableDisposableClearableState };
|
|
37
|
+
//# sourceMappingURL=useUpdatableDisposableClearableState.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableClearableState.mjs","names":[],"sources":["../src/useUpdatableDisposableClearableState.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport { useCallback } from 'react';\nimport {\n UNASSIGNED_STATE,\n type UnassignedState,\n useUpdatableDisposableState,\n} from './useUpdatableDisposableState';\n\ntype UseUpdatableDisposableClearableStateReturnValue<T> = {\n state: T | UnassignedState;\n setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;\n clearState: () => void;\n};\n\n/**\n * The item that `clearState` puts in the underlying state. It is never returned\n * from this hook; the hook reports UNASSIGNED_STATE while it is current.\n */\nconst CLEARED_STATE: unique symbol = Symbol();\ntype ClearedState = typeof CLEARED_STATE;\n\nfunction noop() {}\n\n/**\n * useUpdatableDisposableClearableState\n * - useUpdatableDisposableState, plus clearState.\n * - clearState returns the state to UNASSIGNED_STATE. The item that was in state\n * is disposed on the next commit, exactly as if it had been superseded by\n * setState.\n * - Like setState, clearState throws if called before the initial commit.\n *\n * This is a wrapper around useUpdatableDisposableState: clearing sets a sentinel\n * item with no cleanup, so the underlying hook's commit-time disposal of\n * superseded items disposes the cleared item, and the sentinel is mapped back to\n * UNASSIGNED_STATE on the way out.\n */\nexport function useUpdatableDisposableClearableState<\n T = never,\n>(): UseUpdatableDisposableClearableStateReturnValue<T> {\n const { state, setState } = useUpdatableDisposableState<T | ClearedState>();\n\n const clearState = useCallback(() => {\n setState([CLEARED_STATE, noop]);\n }, [setState]);\n\n return {\n clearState,\n setState,\n state: state === CLEARED_STATE ? UNASSIGNED_STATE : state,\n };\n}\n\n// @ts-ignore\nfunction tsTests() {\n const a = useUpdatableDisposableClearableState();\n // @ts-expect-error\n a.setState([UNASSIGNED_STATE, () => {}]);\n // @ts-expect-error\n a.setState(['asdf', () => {}]);\n const b = useUpdatableDisposableClearableState<string | UnassignedState>();\n // @ts-expect-error\n b.setState([UNASSIGNED_STATE, () => {}]);\n b.setState(['asdf', () => {}]);\n // The cleared sentinel is not part of T, so it cannot be set from outside.\n // @ts-expect-error\n b.setState([CLEARED_STATE, () => {}]);\n}\n"],"mappings":";;;;;;;;AAkBA,MAAM,gBAA+B,QAAQ;AAG7C,SAAS,OAAO;;;;;;;;;;;;;;AAehB,SAAgB,uCAEwC;CACtD,MAAM,EAAE,OAAO,aAAa,6BAA+C;AAM3E,QAAO;EACL,YALiB,kBAAkB;AACnC,YAAS,CAAC,eAAe,KAAK,CAAC;KAC9B,CAAC,SAAS,CAAC;EAIZ;EACA,OAAO,UAAU,gBAAgB,mBAAmB;EACrD"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
const require_useHasCommittedRef = require('./useHasCommittedRef.js');
|
|
1
|
+
const require_useHasCommittedRef = require('./useHasCommittedRef.cjs');
|
|
3
2
|
let react = require("react");
|
|
4
|
-
react = require_rolldown_runtime.__toESM(react);
|
|
5
3
|
|
|
6
4
|
//#region src/useUpdatableDisposableState.ts
|
|
7
5
|
const UNASSIGNED_STATE = Symbol();
|
|
@@ -62,7 +60,11 @@ function useUpdatableDisposableState() {
|
|
|
62
60
|
});
|
|
63
61
|
(0, react.useEffect)(() => {
|
|
64
62
|
return function disposeAllRemainingItems() {
|
|
65
|
-
for (const undisposedICI of undisposedICIs.current)
|
|
63
|
+
for (const undisposedICI of undisposedICIs.current) {
|
|
64
|
+
undisposedICIs.current.delete(undisposedICI);
|
|
65
|
+
undisposedICI.cleanup();
|
|
66
|
+
}
|
|
67
|
+
setStateICI(UNASSIGNED_STATE);
|
|
66
68
|
};
|
|
67
69
|
}, []);
|
|
68
70
|
return {
|
|
@@ -40,4 +40,4 @@ type UseUpdatableDisposableStateReturnValue<T> = {
|
|
|
40
40
|
declare function useUpdatableDisposableState<T = never>(): UseUpdatableDisposableStateReturnValue<T>;
|
|
41
41
|
//#endregion
|
|
42
42
|
export { UNASSIGNED_STATE, UnassignedState, useUpdatableDisposableState };
|
|
43
|
-
//# sourceMappingURL=useUpdatableDisposableState.d.
|
|
43
|
+
//# sourceMappingURL=useUpdatableDisposableState.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableState.d.cts","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"mappings":";;;cAIa,gBAAA;AAAA,KACD,eAAA,UAAyB,gBAAA;AAAA,KAEhC,sCAAA;EACH,KAAA,EAAO,CAAA,GAAI,eAAA;EACX,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;AAAA;;AAJ9C;;;;;AAAsD;;;;;;;;;;;;;;;;;;;;;;;AAuDtD;iBAAgB,2BAAA,WAAA,CAAA,GAEX,sCAAA,CAAuC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUpdatableDisposableState.d.mts","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableState.d.mts","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"mappings":";;;cAIa,gBAAA;AAAA,KACD,eAAA,UAAyB,gBAAA;AAAA,KAEhC,sCAAA;EACH,KAAA,EAAO,CAAA,GAAI,eAAA;EACX,QAAA,GAAW,IAAA,EAAM,eAAA,CAAgB,OAAA,CAAQ,CAAA,EAAG,eAAA;AAAA;;AAJ9C;;;;;AAAsD;;;;;;;;;;;;;;;;;;;;;;;AAuDtD;iBAAgB,2BAAA,WAAA,CAAA,GAEX,sCAAA,CAAuC,CAAA"}
|
|
@@ -60,7 +60,11 @@ function useUpdatableDisposableState() {
|
|
|
60
60
|
});
|
|
61
61
|
useEffect(() => {
|
|
62
62
|
return function disposeAllRemainingItems() {
|
|
63
|
-
for (const undisposedICI of undisposedICIs.current)
|
|
63
|
+
for (const undisposedICI of undisposedICIs.current) {
|
|
64
|
+
undisposedICIs.current.delete(undisposedICI);
|
|
65
|
+
undisposedICI.cleanup();
|
|
66
|
+
}
|
|
67
|
+
setStateICI(UNASSIGNED_STATE);
|
|
64
68
|
};
|
|
65
69
|
}, []);
|
|
66
70
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUpdatableDisposableState.mjs","names":[
|
|
1
|
+
{"version":3,"file":"useUpdatableDisposableState.mjs","names":[],"sources":["../src/useUpdatableDisposableState.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useHasCommittedRef } from './useHasCommittedRef';\n\nexport const UNASSIGNED_STATE: unique symbol = Symbol();\nexport type UnassignedState = typeof UNASSIGNED_STATE;\n\ntype UseUpdatableDisposableStateReturnValue<T> = {\n state: T | UnassignedState;\n setState: (pair: ItemCleanupPair<Exclude<T, UnassignedState>>) => void;\n};\n\n/**\n * ICI stands for ItemCleanupIndex. Use a short name because it shows up a lot.\n *\n * Like an ItemCleanupPair<T>, but with an additional index and as a struct\n * for readability.\n *\n * Interally, we must keep track of the index of the state change. The disposable\n * items that are set in state are not guaranteed to be distinct according to ===,\n * as in `setState([1, dispose1]); setState([1, dispose2])`. Following this, we\n * would expect dispose1 to be called on commit. If state items were compared for\n * ===, then dispose1 would not be called in such a situation.\n *\n * Note that this comes at a runtime cost, and we may want to expose APIs that do\n * not incur this runtime cost, for example in cases where every disposable item is\n * distinguishable via ===.\n */\ntype ICI<T> = { item: T; cleanup: () => void; index: number };\n\n/**\n * useUpdatableDisposableState\n * - Returns a { state, setItem } object.\n * - setItem accepts an ItemCleanupPair<T>, and throws if called before commit.\n * - setItem sets the T in state and adds it to a set.\n * - React's behavior is that when the hook commits, whatever item is currently\n * returned from the useState hook is the oldest item which will ever be returned\n * from that useState hook. (More newly created ones can later be returned with\n * concurrent mode.)\n * - When this hook commits, all items up to, but not including, the item currently\n * returned from the useState hook are disposed and removed from the set.\n *\n * Calling setState before the hook commits:\n * - Calling setState before the hook commits is disallowed because until the hook\n * commits, React will not schedule any unmount callbacks, meaning that if this\n * hook never commits, any disposable items passed to setState will never be\n * disposed.\n * - We also cannot store them in some cache, because multiple components can share\n * the same cache location (for example, if they are loading the same query from\n * multiple components), so updating the cache with the disposable item will cause\n * both components to show the updated data, which is almost certainly a bug.\n * - Note that calling setState before commit is probably an anti-pattern! Consider\n * not doing it.\n * - If you must, the workaround is to lazily load the disposable item with\n * useDisposableState or useLazyDisposableState, and update the cache location\n * instead of calling setState before commit. One can update the cache location\n * by calling setState on some parent component that has already mounted, and\n * therefore passing in different props.\n * - This may only work in concurrent mode, though.\n */\nexport function useUpdatableDisposableState<\n T = never,\n>(): UseUpdatableDisposableStateReturnValue<T> {\n const hasCommittedRef = useHasCommittedRef();\n\n const undisposedICIs = useRef(new Set<ICI<T>>());\n const setStateCountRef = useRef(0);\n\n const [stateICI, setStateICI] = useState<ICI<T> | UnassignedState>(\n UNASSIGNED_STATE,\n );\n\n const setStateAfterCommit = useCallback(\n (itemCleanupPair: ItemCleanupPair<T>) => {\n if (!hasCommittedRef.current) {\n throw new Error(\n 'Calling setState before the component has committed is unsafe and disallowed.',\n );\n }\n\n const ici: ICI<T> = {\n item: itemCleanupPair[0],\n cleanup: itemCleanupPair[1],\n index: setStateCountRef.current,\n };\n setStateCountRef.current++;\n undisposedICIs.current.add(ici);\n setStateICI(ici);\n },\n [setStateICI],\n );\n\n useEffect(function cleanupUnreachableItems() {\n const indexInState = stateICI !== UNASSIGNED_STATE ? stateICI.index : 0;\n\n if (indexInState === 0) {\n return;\n }\n\n for (const undisposedICI of undisposedICIs.current) {\n if (undisposedICI.index === indexInState) {\n break;\n }\n undisposedICIs.current.delete(undisposedICI);\n undisposedICI.cleanup();\n }\n });\n\n useEffect(() => {\n return function disposeAllRemainingItems() {\n for (const undisposedICI of undisposedICIs.current) {\n undisposedICIs.current.delete(undisposedICI);\n undisposedICI.cleanup();\n }\n setStateICI(UNASSIGNED_STATE);\n };\n }, []);\n\n return {\n setState: setStateAfterCommit,\n state: stateICI !== UNASSIGNED_STATE ? stateICI.item : UNASSIGNED_STATE,\n };\n}\n\n// @ts-ignore\nfunction tsTests() {\n const a = useUpdatableDisposableState();\n // @ts-expect-error\n a.setState([UNASSIGNED_STATE, () => {}]);\n // @ts-expect-error\n a.setState(['asdf', () => {}]);\n const b = useUpdatableDisposableState<string | UnassignedState>();\n // @ts-expect-error\n b.setState([UNASSIGNED_STATE, () => {}]);\n b.setState(['asdf', () => {}]);\n}\n"],"mappings":";;;;AAIA,MAAa,mBAAkC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDvD,SAAgB,8BAE+B;CAC7C,MAAM,kBAAkB,oBAAoB;CAE5C,MAAM,iBAAiB,uBAAO,IAAI,KAAa,CAAC;CAChD,MAAM,mBAAmB,OAAO,EAAE;CAElC,MAAM,CAAC,UAAU,eAAe,SAC9B,iBACD;CAED,MAAM,sBAAsB,aACzB,oBAAwC;AACvC,MAAI,CAAC,gBAAgB,QACnB,OAAM,IAAI,MACR,gFACD;EAGH,MAAM,MAAc;GAClB,MAAM,gBAAgB;GACtB,SAAS,gBAAgB;GACzB,OAAO,iBAAiB;GACzB;AACD,mBAAiB;AACjB,iBAAe,QAAQ,IAAI,IAAI;AAC/B,cAAY,IAAI;IAElB,CAAC,YAAY,CACd;AAED,WAAU,SAAS,0BAA0B;EAC3C,MAAM,eAAe,aAAa,mBAAmB,SAAS,QAAQ;AAEtE,MAAI,iBAAiB,EACnB;AAGF,OAAK,MAAM,iBAAiB,eAAe,SAAS;AAClD,OAAI,cAAc,UAAU,aAC1B;AAEF,kBAAe,QAAQ,OAAO,cAAc;AAC5C,iBAAc,SAAS;;GAEzB;AAEF,iBAAgB;AACd,SAAO,SAAS,2BAA2B;AACzC,QAAK,MAAM,iBAAiB,eAAe,SAAS;AAClD,mBAAe,QAAQ,OAAO,cAAc;AAC5C,kBAAc,SAAS;;AAEzB,eAAY,iBAAiB;;IAE9B,EAAE,CAAC;AAEN,QAAO;EACL,UAAU;EACV,OAAO,aAAa,mBAAmB,SAAS,OAAO;EACxD"}
|