@finos/legend-application 16.0.91 → 16.0.93
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/lib/__lib__/LegendApplicationNavigation.d.ts.map +1 -1
- package/lib/__lib__/LegendApplicationNavigation.js +1 -1
- package/lib/__lib__/LegendApplicationNavigation.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/package.json +1 -1
- package/lib/util/URLUtils.d.ts +8 -1
- package/lib/util/URLUtils.d.ts.map +1 -1
- package/lib/util/URLUtils.js +76 -21
- package/lib/util/URLUtils.js.map +1 -1
- package/package.json +3 -3
- package/src/__lib__/LegendApplicationNavigation.ts +1 -1
- package/src/util/URLUtils.ts +93 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendApplicationNavigation.d.ts","sourceRoot":"","sources":["../../src/__lib__/LegendApplicationNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,oBAAY,8BAA8B;IACxC,mBAAmB,sBAAsB;CAC1C;AAED;;GAEG;AACH,eAAO,MAAM,6DAA6D,GACxE,sBAAsB,MAAM,EAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,WAAW,MAAM,EACjB,YAAY,MAAM,GAAG,SAAS,KAC7B,MAK8C,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,uDAAuD,GAClE,wBAAwB,MAAM,EAC9B,YAAY,MAAM,KACjB,MAGE,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,2DAA2D,GACtE,wBAAwB,MAAM,EAC9B,iBAAiB,MAAM,EACvB,iBAAiB,MAAM,KACtB,
|
|
1
|
+
{"version":3,"file":"LegendApplicationNavigation.d.ts","sourceRoot":"","sources":["../../src/__lib__/LegendApplicationNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,oBAAY,8BAA8B;IACxC,mBAAmB,sBAAsB;CAC1C;AAED;;GAEG;AACH,eAAO,MAAM,6DAA6D,GACxE,sBAAsB,MAAM,EAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,WAAW,MAAM,EACjB,YAAY,MAAM,GAAG,SAAS,KAC7B,MAK8C,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,uDAAuD,GAClE,wBAAwB,MAAM,EAC9B,YAAY,MAAM,KACjB,MAGE,CAAC;AAEN;;GAEG;AACH,eAAO,MAAM,2DAA2D,GACtE,wBAAwB,MAAM,EAC9B,iBAAiB,MAAM,EACvB,iBAAiB,MAAM,KACtB,MACwI,CAAC"}
|
|
@@ -29,5 +29,5 @@ export const EXTERNAL_APPLICATION_NAVIGATION__generateNewDataCubeUrl = (dataCube
|
|
|
29
29
|
/**
|
|
30
30
|
* @external_application_navigation This depends on Registry routing and is hardcoded so it's potentially brittle
|
|
31
31
|
*/
|
|
32
|
-
export const EXTERNAL_APPLICATION_NAVIGATION__generateRegistryLineageUrl = (registryApplicationUrl, dataProductName, accessPointName) => `${registryApplicationUrl}
|
|
32
|
+
export const EXTERNAL_APPLICATION_NAVIGATION__generateRegistryLineageUrl = (registryApplicationUrl, dataProductName, accessPointName) => `${registryApplicationUrl}/#/lineage/lakehouse/dataProduct/${dataProductName.toUpperCase()}/accessPoint/${accessPointName.toUpperCase()}`;
|
|
33
33
|
//# sourceMappingURL=LegendApplicationNavigation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendApplicationNavigation.js","sourceRoot":"","sources":["../../src/__lib__/LegendApplicationNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,CAAN,IAAY,8BAEX;AAFD,WAAY,8BAA8B;IACxC,2EAAyC,CAAA;AAC3C,CAAC,EAFW,8BAA8B,KAA9B,8BAA8B,QAEzC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,6DAA6D,GAAG,CAC3E,oBAA4B,EAC5B,OAAe,EACf,UAAkB,EAClB,SAAiB,EACjB,UAA8B,EACtB,EAAE,CACV,GAAG,oBAAoB,iBAAiB,sBAAsB,CAC5D,OAAO,EACP,UAAU,EACV,SAAS,CACV,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,MAAM,uDAAuD,GAAG,CACrE,sBAA8B,EAC9B,UAAkB,EACV,EAAE,CACV,GAAG,sBAAsB,eAAe,kBAAkB,CACxD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CACjC,EAAE,CAAC;AAEN;;GAEG;AACH,MAAM,CAAC,MAAM,2DAA2D,GAAG,CACzE,sBAA8B,EAC9B,eAAuB,EACvB,eAAuB,EACf,EAAE,CACV,GAAG,sBAAsB,
|
|
1
|
+
{"version":3,"file":"LegendApplicationNavigation.js","sourceRoot":"","sources":["../../src/__lib__/LegendApplicationNavigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,CAAN,IAAY,8BAEX;AAFD,WAAY,8BAA8B;IACxC,2EAAyC,CAAA;AAC3C,CAAC,EAFW,8BAA8B,KAA9B,8BAA8B,QAEzC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,6DAA6D,GAAG,CAC3E,oBAA4B,EAC5B,OAAe,EACf,UAAkB,EAClB,SAAiB,EACjB,UAA8B,EACtB,EAAE,CACV,GAAG,oBAAoB,iBAAiB,sBAAsB,CAC5D,OAAO,EACP,UAAU,EACV,SAAS,CACV,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,MAAM,uDAAuD,GAAG,CACrE,sBAA8B,EAC9B,UAAkB,EACV,EAAE,CACV,GAAG,sBAAsB,eAAe,kBAAkB,CACxD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CACjC,EAAE,CAAC;AAEN;;GAEG;AACH,MAAM,CAAC,MAAM,2DAA2D,GAAG,CACzE,sBAA8B,EAC9B,eAAuB,EACvB,eAAuB,EACf,EAAE,CACV,GAAG,sBAAsB,oCAAoC,eAAe,CAAC,WAAW,EAAE,gBAAgB,eAAe,CAAC,WAAW,EAAE,EAAE,CAAC"}
|
package/lib/index.css
CHANGED
package/lib/package.json
CHANGED
package/lib/util/URLUtils.d.ts
CHANGED
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
import type { SetURLSearchParams } from 'react-router';
|
|
17
17
|
/**
|
|
18
18
|
* Util hook to keep a state variable in sync with a URL search parameter.
|
|
19
|
+
* This hook syncs from URL to state if the state is null/undefined (so
|
|
20
|
+
* initial value is set from URL) and from state to URL otherwise.
|
|
21
|
+
*
|
|
22
|
+
* This hook properly queues setSearchParams calls to ensure all updates
|
|
23
|
+
* are applied, working around react-router's limitation where multiple
|
|
24
|
+
* calls to setSearchParams in the same tick don't build on each other.
|
|
25
|
+
* See: https://github.com/remix-run/react-router/issues/9304
|
|
19
26
|
*
|
|
20
27
|
* @param stateVar the state variable to sync
|
|
21
28
|
* @param updateStateVar setter function to update the state variable (should be memoized with useCallback)
|
|
@@ -24,5 +31,5 @@ import type { SetURLSearchParams } from 'react-router';
|
|
|
24
31
|
* @param setSearchParams function to update the URL search parameters (i.e., from useSearchParams)
|
|
25
32
|
* @param initializedCallback function to check if the underlying state is initialized and ready to sync with URL (should be memoized with useCallback)
|
|
26
33
|
*/
|
|
27
|
-
export declare const useSyncStateAndSearchParam: (stateVar: string | boolean | number | null | undefined, updateStateVar: (val: string | null) => void, searchParamKey: string, searchParamValue: string | null, setSearchParams: SetURLSearchParams, initializedCallback: () => boolean) => void;
|
|
34
|
+
export declare const useSyncStateAndSearchParam: (stateVar: string | boolean | number | null | undefined, updateStateVar: (val: string | null) => void, searchParamKey: string, searchParamValue: string | null, setSearchParams: SetURLSearchParams, initializedCallback: () => boolean, clearParamOnUnmount?: boolean) => void;
|
|
28
35
|
//# sourceMappingURL=URLUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"URLUtils.d.ts","sourceRoot":"","sources":["../../src/util/URLUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"URLUtils.d.ts","sourceRoot":"","sources":["../../src/util/URLUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAwDvD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,GACrC,UAAU,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACtD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,EAC5C,gBAAgB,MAAM,EACtB,kBAAkB,MAAM,GAAG,IAAI,EAC/B,iBAAiB,kBAAkB,EACnC,qBAAqB,MAAM,OAAO,EAClC,sBAAqB,OAAc,KAClC,IAwCF,CAAC"}
|
package/lib/util/URLUtils.js
CHANGED
|
@@ -13,9 +13,61 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { useEffect } from 'react';
|
|
16
|
+
import { useEffect, useRef } from 'react';
|
|
17
|
+
/**
|
|
18
|
+
* Module-level queue for pending search param updates.
|
|
19
|
+
* This ensures all instances of the hook share the same queue,
|
|
20
|
+
* allowing updates to be batched together and applied in a single
|
|
21
|
+
* setSearchParams call.
|
|
22
|
+
*
|
|
23
|
+
* This is necessary because react-router's setSearchParams does not
|
|
24
|
+
* support queueing like React's setState does. Multiple calls to
|
|
25
|
+
* setSearchParams in the same tick will not build on the prior value.
|
|
26
|
+
* See: https://github.com/remix-run/react-router/issues/9304
|
|
27
|
+
*/
|
|
28
|
+
const pendingUpdates = new Map();
|
|
29
|
+
let flushScheduled = false;
|
|
30
|
+
let currentSetSearchParams = null;
|
|
31
|
+
const flushUpdates = () => {
|
|
32
|
+
if (pendingUpdates.size === 0 || !currentSetSearchParams) {
|
|
33
|
+
flushScheduled = false;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const setSearchParams = currentSetSearchParams;
|
|
37
|
+
const updates = new Map(pendingUpdates);
|
|
38
|
+
pendingUpdates.clear();
|
|
39
|
+
flushScheduled = false;
|
|
40
|
+
setSearchParams((params) => {
|
|
41
|
+
const newParams = new URLSearchParams(params);
|
|
42
|
+
updates.forEach((value, key) => {
|
|
43
|
+
if (value !== null) {
|
|
44
|
+
newParams.set(key, value);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
newParams.delete(key);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return newParams;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const queueUpdate = (key, value, setSearchParams) => {
|
|
54
|
+
pendingUpdates.set(key, value);
|
|
55
|
+
currentSetSearchParams = setSearchParams;
|
|
56
|
+
if (!flushScheduled) {
|
|
57
|
+
flushScheduled = true;
|
|
58
|
+
// Use queueMicrotask to batch updates in the same tick
|
|
59
|
+
queueMicrotask(flushUpdates);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
17
62
|
/**
|
|
18
63
|
* Util hook to keep a state variable in sync with a URL search parameter.
|
|
64
|
+
* This hook syncs from URL to state if the state is null/undefined (so
|
|
65
|
+
* initial value is set from URL) and from state to URL otherwise.
|
|
66
|
+
*
|
|
67
|
+
* This hook properly queues setSearchParams calls to ensure all updates
|
|
68
|
+
* are applied, working around react-router's limitation where multiple
|
|
69
|
+
* calls to setSearchParams in the same tick don't build on each other.
|
|
70
|
+
* See: https://github.com/remix-run/react-router/issues/9304
|
|
19
71
|
*
|
|
20
72
|
* @param stateVar the state variable to sync
|
|
21
73
|
* @param updateStateVar setter function to update the state variable (should be memoized with useCallback)
|
|
@@ -24,34 +76,37 @@ import { useEffect } from 'react';
|
|
|
24
76
|
* @param setSearchParams function to update the URL search parameters (i.e., from useSearchParams)
|
|
25
77
|
* @param initializedCallback function to check if the underlying state is initialized and ready to sync with URL (should be memoized with useCallback)
|
|
26
78
|
*/
|
|
27
|
-
export const useSyncStateAndSearchParam = (stateVar, updateStateVar, searchParamKey, searchParamValue, setSearchParams, initializedCallback) => {
|
|
28
|
-
//
|
|
79
|
+
export const useSyncStateAndSearchParam = (stateVar, updateStateVar, searchParamKey, searchParamValue, setSearchParams, initializedCallback, clearParamOnUnmount = true) => {
|
|
80
|
+
// Use a ref to make setSearchParams stable
|
|
81
|
+
// react-router's setSearchParams is not stable and changes on every render
|
|
82
|
+
// See: https://github.com/remix-run/react-router/issues/9304
|
|
83
|
+
const setSearchParamsRef = useRef(setSearchParams);
|
|
84
|
+
setSearchParamsRef.current = setSearchParams;
|
|
85
|
+
// Sync state with URL search param if state is null/undefined
|
|
29
86
|
useEffect(() => {
|
|
30
|
-
if (initializedCallback()
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
updateStateVar(urlParamValue);
|
|
87
|
+
if (initializedCallback() &&
|
|
88
|
+
(stateVar === null || stateVar === undefined)) {
|
|
89
|
+
updateStateVar(searchParamValue);
|
|
34
90
|
}
|
|
35
|
-
}, [initializedCallback,
|
|
91
|
+
}, [initializedCallback, searchParamValue, stateVar, updateStateVar]);
|
|
36
92
|
// Sync URL search param with state
|
|
37
93
|
useEffect(() => {
|
|
38
94
|
if (initializedCallback()) {
|
|
39
|
-
// When state changes,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return newParams;
|
|
45
|
-
});
|
|
95
|
+
// When state changes, queue URL param update
|
|
96
|
+
// Using the queueing mechanism ensures all updates are applied
|
|
97
|
+
// even when multiple hooks call setSearchParams in the same tick
|
|
98
|
+
if (stateVar !== null && stateVar !== undefined) {
|
|
99
|
+
queueUpdate(searchParamKey, String(stateVar), setSearchParamsRef.current);
|
|
46
100
|
}
|
|
47
101
|
else {
|
|
48
|
-
|
|
49
|
-
const newParams = new URLSearchParams(params);
|
|
50
|
-
newParams.delete(searchParamKey);
|
|
51
|
-
return newParams;
|
|
52
|
-
});
|
|
102
|
+
queueUpdate(searchParamKey, null, setSearchParamsRef.current);
|
|
53
103
|
}
|
|
54
104
|
}
|
|
55
|
-
|
|
105
|
+
return () => {
|
|
106
|
+
if (clearParamOnUnmount) {
|
|
107
|
+
queueUpdate(searchParamKey, null, setSearchParamsRef.current);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}, [clearParamOnUnmount, initializedCallback, searchParamKey, stateVar]);
|
|
56
111
|
};
|
|
57
112
|
//# sourceMappingURL=URLUtils.js.map
|
package/lib/util/URLUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"URLUtils.js","sourceRoot":"","sources":["../../src/util/URLUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"URLUtils.js","sourceRoot":"","sources":["../../src/util/URLUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos/legend-application",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.93",
|
|
4
4
|
"description": "Legend application core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"legend",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"test:watch": "jest --watch"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@finos/legend-art": "7.1.
|
|
48
|
+
"@finos/legend-art": "7.1.141",
|
|
49
49
|
"@finos/legend-shared": "11.0.22",
|
|
50
50
|
"@finos/legend-storage": "3.0.141",
|
|
51
51
|
"@types/react": "19.0.10",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"xterm-addon-webgl": "0.16.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@finos/legend-dev-utils": "2.2.
|
|
70
|
+
"@finos/legend-dev-utils": "2.2.6",
|
|
71
71
|
"@jest/globals": "29.7.0",
|
|
72
72
|
"@testing-library/dom": "10.4.0",
|
|
73
73
|
"@testing-library/react": "16.2.0",
|
|
@@ -55,4 +55,4 @@ export const EXTERNAL_APPLICATION_NAVIGATION__generateRegistryLineageUrl = (
|
|
|
55
55
|
dataProductName: string,
|
|
56
56
|
accessPointName: string,
|
|
57
57
|
): string =>
|
|
58
|
-
`${registryApplicationUrl}
|
|
58
|
+
`${registryApplicationUrl}/#/lineage/lakehouse/dataProduct/${dataProductName.toUpperCase()}/accessPoint/${accessPointName.toUpperCase()}`;
|
package/src/util/URLUtils.ts
CHANGED
|
@@ -14,11 +14,72 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { useEffect } from 'react';
|
|
17
|
+
import { useEffect, useRef } from 'react';
|
|
18
18
|
import type { SetURLSearchParams } from 'react-router';
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Module-level queue for pending search param updates.
|
|
22
|
+
* This ensures all instances of the hook share the same queue,
|
|
23
|
+
* allowing updates to be batched together and applied in a single
|
|
24
|
+
* setSearchParams call.
|
|
25
|
+
*
|
|
26
|
+
* This is necessary because react-router's setSearchParams does not
|
|
27
|
+
* support queueing like React's setState does. Multiple calls to
|
|
28
|
+
* setSearchParams in the same tick will not build on the prior value.
|
|
29
|
+
* See: https://github.com/remix-run/react-router/issues/9304
|
|
30
|
+
*/
|
|
31
|
+
const pendingUpdates: Map<string, string | null> = new Map();
|
|
32
|
+
let flushScheduled = false;
|
|
33
|
+
let currentSetSearchParams: SetURLSearchParams | null = null;
|
|
34
|
+
|
|
35
|
+
const flushUpdates = (): void => {
|
|
36
|
+
if (pendingUpdates.size === 0 || !currentSetSearchParams) {
|
|
37
|
+
flushScheduled = false;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const setSearchParams = currentSetSearchParams;
|
|
42
|
+
const updates = new Map(pendingUpdates);
|
|
43
|
+
pendingUpdates.clear();
|
|
44
|
+
flushScheduled = false;
|
|
45
|
+
|
|
46
|
+
setSearchParams((params) => {
|
|
47
|
+
const newParams = new URLSearchParams(params);
|
|
48
|
+
updates.forEach((value, key) => {
|
|
49
|
+
if (value !== null) {
|
|
50
|
+
newParams.set(key, value);
|
|
51
|
+
} else {
|
|
52
|
+
newParams.delete(key);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return newParams;
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const queueUpdate = (
|
|
60
|
+
key: string,
|
|
61
|
+
value: string | null,
|
|
62
|
+
setSearchParams: SetURLSearchParams,
|
|
63
|
+
): void => {
|
|
64
|
+
pendingUpdates.set(key, value);
|
|
65
|
+
currentSetSearchParams = setSearchParams;
|
|
66
|
+
|
|
67
|
+
if (!flushScheduled) {
|
|
68
|
+
flushScheduled = true;
|
|
69
|
+
// Use queueMicrotask to batch updates in the same tick
|
|
70
|
+
queueMicrotask(flushUpdates);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
20
74
|
/**
|
|
21
75
|
* Util hook to keep a state variable in sync with a URL search parameter.
|
|
76
|
+
* This hook syncs from URL to state if the state is null/undefined (so
|
|
77
|
+
* initial value is set from URL) and from state to URL otherwise.
|
|
78
|
+
*
|
|
79
|
+
* This hook properly queues setSearchParams calls to ensure all updates
|
|
80
|
+
* are applied, working around react-router's limitation where multiple
|
|
81
|
+
* calls to setSearchParams in the same tick don't build on each other.
|
|
82
|
+
* See: https://github.com/remix-run/react-router/issues/9304
|
|
22
83
|
*
|
|
23
84
|
* @param stateVar the state variable to sync
|
|
24
85
|
* @param updateStateVar setter function to update the state variable (should be memoized with useCallback)
|
|
@@ -34,33 +95,45 @@ export const useSyncStateAndSearchParam = (
|
|
|
34
95
|
searchParamValue: string | null,
|
|
35
96
|
setSearchParams: SetURLSearchParams,
|
|
36
97
|
initializedCallback: () => boolean,
|
|
98
|
+
clearParamOnUnmount: boolean = true,
|
|
37
99
|
): void => {
|
|
38
|
-
//
|
|
100
|
+
// Use a ref to make setSearchParams stable
|
|
101
|
+
// react-router's setSearchParams is not stable and changes on every render
|
|
102
|
+
// See: https://github.com/remix-run/react-router/issues/9304
|
|
103
|
+
const setSearchParamsRef = useRef(setSearchParams);
|
|
104
|
+
setSearchParamsRef.current = setSearchParams;
|
|
105
|
+
|
|
106
|
+
// Sync state with URL search param if state is null/undefined
|
|
39
107
|
useEffect(() => {
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
108
|
+
if (
|
|
109
|
+
initializedCallback() &&
|
|
110
|
+
(stateVar === null || stateVar === undefined)
|
|
111
|
+
) {
|
|
112
|
+
updateStateVar(searchParamValue);
|
|
44
113
|
}
|
|
45
|
-
}, [initializedCallback,
|
|
114
|
+
}, [initializedCallback, searchParamValue, stateVar, updateStateVar]);
|
|
46
115
|
|
|
47
116
|
// Sync URL search param with state
|
|
48
117
|
useEffect(() => {
|
|
49
118
|
if (initializedCallback()) {
|
|
50
|
-
// When state changes,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
119
|
+
// When state changes, queue URL param update
|
|
120
|
+
// Using the queueing mechanism ensures all updates are applied
|
|
121
|
+
// even when multiple hooks call setSearchParams in the same tick
|
|
122
|
+
if (stateVar !== null && stateVar !== undefined) {
|
|
123
|
+
queueUpdate(
|
|
124
|
+
searchParamKey,
|
|
125
|
+
String(stateVar),
|
|
126
|
+
setSearchParamsRef.current,
|
|
127
|
+
);
|
|
57
128
|
} else {
|
|
58
|
-
|
|
59
|
-
const newParams = new URLSearchParams(params);
|
|
60
|
-
newParams.delete(searchParamKey);
|
|
61
|
-
return newParams;
|
|
62
|
-
});
|
|
129
|
+
queueUpdate(searchParamKey, null, setSearchParamsRef.current);
|
|
63
130
|
}
|
|
64
131
|
}
|
|
65
|
-
|
|
132
|
+
|
|
133
|
+
return () => {
|
|
134
|
+
if (clearParamOnUnmount) {
|
|
135
|
+
queueUpdate(searchParamKey, null, setSearchParamsRef.current);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}, [clearParamOnUnmount, initializedCallback, searchParamKey, stateVar]);
|
|
66
139
|
};
|