@vitessce/vit-s 2.0.3 → 3.0.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.
Files changed (215) hide show
  1. package/dist/index.js +44072 -0
  2. package/dist-tsc/CallbackPublisher.d.ts +18 -0
  3. package/dist-tsc/CallbackPublisher.d.ts.map +1 -0
  4. package/dist-tsc/CallbackPublisher.js +62 -0
  5. package/dist-tsc/LoadingIndicator.d.ts +2 -0
  6. package/dist-tsc/LoadingIndicator.d.ts.map +1 -0
  7. package/dist-tsc/LoadingIndicator.js +26 -0
  8. package/dist-tsc/TitleInfo.d.ts +2 -0
  9. package/dist-tsc/TitleInfo.d.ts.map +1 -0
  10. package/dist-tsc/TitleInfo.js +74 -0
  11. package/dist-tsc/VitS.d.ts +50 -0
  12. package/dist-tsc/VitS.d.ts.map +1 -0
  13. package/dist-tsc/VitS.js +139 -0
  14. package/dist-tsc/VitessceGrid.d.ts +23 -0
  15. package/dist-tsc/VitessceGrid.d.ts.map +1 -0
  16. package/dist-tsc/VitessceGrid.js +63 -0
  17. package/dist-tsc/VitessceGrid.test.d.ts +2 -0
  18. package/dist-tsc/VitessceGrid.test.d.ts.map +1 -0
  19. package/dist-tsc/VitessceGrid.test.js +43 -0
  20. package/dist-tsc/Warning.d.ts +2 -0
  21. package/dist-tsc/Warning.d.ts.map +1 -0
  22. package/dist-tsc/Warning.js +45 -0
  23. package/dist-tsc/classNames.d.ts +8 -0
  24. package/dist-tsc/classNames.d.ts.map +1 -0
  25. package/dist-tsc/classNames.js +8 -0
  26. package/dist-tsc/data/AbstractLoader.d.ts +22 -0
  27. package/dist-tsc/data/AbstractLoader.d.ts.map +1 -0
  28. package/dist-tsc/data/AbstractLoader.js +18 -0
  29. package/dist-tsc/data/AbstractTwoStepLoader.d.ts +6 -0
  30. package/dist-tsc/data/AbstractTwoStepLoader.d.ts.map +1 -0
  31. package/dist-tsc/data/AbstractTwoStepLoader.js +7 -0
  32. package/dist-tsc/data/LoaderResult.d.ts +12 -0
  33. package/dist-tsc/data/LoaderResult.d.ts.map +1 -0
  34. package/dist-tsc/data/LoaderResult.js +12 -0
  35. package/dist-tsc/data/index.d.ts +4 -0
  36. package/dist-tsc/data/index.d.ts.map +1 -0
  37. package/dist-tsc/data/index.js +3 -0
  38. package/dist-tsc/data/loader-registry.d.ts +9 -0
  39. package/dist-tsc/data/loader-registry.d.ts.map +1 -0
  40. package/dist-tsc/data/loader-registry.js +27 -0
  41. package/dist-tsc/data-hook-utils.d.ts +65 -0
  42. package/dist-tsc/data-hook-utils.d.ts.map +1 -0
  43. package/dist-tsc/data-hook-utils.js +191 -0
  44. package/dist-tsc/data-hooks.d.ts +73 -0
  45. package/dist-tsc/data-hooks.d.ts.map +1 -0
  46. package/dist-tsc/data-hooks.js +254 -0
  47. package/dist-tsc/errors/AbstractLoaderError.d.ts +10 -0
  48. package/dist-tsc/errors/AbstractLoaderError.d.ts.map +1 -0
  49. package/dist-tsc/errors/AbstractLoaderError.js +13 -0
  50. package/dist-tsc/errors/DataSourceFetchError.d.ts +8 -0
  51. package/dist-tsc/errors/DataSourceFetchError.d.ts.map +1 -0
  52. package/dist-tsc/errors/DataSourceFetchError.js +13 -0
  53. package/dist-tsc/errors/DatasetNotFoundError.d.ts +6 -0
  54. package/dist-tsc/errors/DatasetNotFoundError.d.ts.map +1 -0
  55. package/dist-tsc/errors/DatasetNotFoundError.js +17 -0
  56. package/dist-tsc/errors/LoaderNotFoundError.d.ts +10 -0
  57. package/dist-tsc/errors/LoaderNotFoundError.d.ts.map +1 -0
  58. package/dist-tsc/errors/LoaderNotFoundError.js +17 -0
  59. package/dist-tsc/errors/LoaderValidationError.d.ts +10 -0
  60. package/dist-tsc/errors/LoaderValidationError.d.ts.map +1 -0
  61. package/dist-tsc/errors/LoaderValidationError.js +15 -0
  62. package/dist-tsc/errors/index.d.ts +6 -0
  63. package/dist-tsc/errors/index.d.ts.map +1 -0
  64. package/dist-tsc/errors/index.js +5 -0
  65. package/dist-tsc/hooks.d.ts +76 -0
  66. package/dist-tsc/hooks.d.ts.map +1 -0
  67. package/dist-tsc/hooks.js +262 -0
  68. package/dist-tsc/index.d.ts +12 -0
  69. package/dist-tsc/index.d.ts.map +1 -0
  70. package/dist-tsc/index.js +11 -17
  71. package/dist-tsc/mui-utils.d.ts +2 -0
  72. package/dist-tsc/mui-utils.d.ts.map +1 -0
  73. package/dist-tsc/mui-utils.js +44 -0
  74. package/dist-tsc/plugins.test.fixtures.d.ts +61 -0
  75. package/dist-tsc/plugins.test.fixtures.d.ts.map +1 -0
  76. package/dist-tsc/plugins.test.fixtures.js +76 -0
  77. package/dist-tsc/shared-mui/components.d.ts +2 -0
  78. package/dist-tsc/shared-mui/components.d.ts.map +1 -0
  79. package/dist-tsc/shared-mui/components.js +29 -0
  80. package/dist-tsc/shared-mui/container.d.ts +2 -0
  81. package/dist-tsc/shared-mui/container.d.ts.map +1 -0
  82. package/dist-tsc/shared-mui/container.js +211 -0
  83. package/dist-tsc/shared-mui/styles.d.ts +5 -0
  84. package/dist-tsc/shared-mui/styles.d.ts.map +1 -0
  85. package/dist-tsc/shared-mui/styles.js +109 -0
  86. package/dist-tsc/shared-plot-options/CellColorEncodingOption.d.ts +2 -0
  87. package/dist-tsc/shared-plot-options/CellColorEncodingOption.d.ts.map +1 -0
  88. package/dist-tsc/shared-plot-options/CellColorEncodingOption.js +17 -0
  89. package/dist-tsc/shared-plot-options/OptionSelect.d.ts +2 -0
  90. package/dist-tsc/shared-plot-options/OptionSelect.d.ts.map +1 -0
  91. package/dist-tsc/shared-plot-options/OptionSelect.js +12 -0
  92. package/dist-tsc/shared-plot-options/OptionsContainer.d.ts +2 -0
  93. package/dist-tsc/shared-plot-options/OptionsContainer.d.ts.map +1 -0
  94. package/dist-tsc/shared-plot-options/OptionsContainer.js +9 -0
  95. package/dist-tsc/shared-plot-options/index.d.ts +5 -0
  96. package/dist-tsc/shared-plot-options/index.d.ts.map +1 -0
  97. package/dist-tsc/shared-plot-options/index.js +4 -0
  98. package/dist-tsc/shared-plot-options/styles.d.ts +2 -0
  99. package/dist-tsc/shared-plot-options/styles.d.ts.map +1 -0
  100. package/dist-tsc/shared-plot-options/styles.js +48 -0
  101. package/dist-tsc/state/hooks.d.ts +242 -0
  102. package/dist-tsc/state/hooks.d.ts.map +1 -0
  103. package/dist-tsc/state/hooks.js +615 -0
  104. package/dist-tsc/title-styles.d.ts +2 -0
  105. package/dist-tsc/title-styles.d.ts.map +1 -0
  106. package/dist-tsc/title-styles.js +72 -0
  107. package/dist-tsc/view-config-utils.d.ts +31 -0
  108. package/dist-tsc/view-config-utils.d.ts.map +1 -0
  109. package/dist-tsc/view-config-utils.js +240 -0
  110. package/dist-tsc/view-config-utils.test.d.ts +2 -0
  111. package/dist-tsc/view-config-utils.test.d.ts.map +1 -0
  112. package/dist-tsc/view-config-utils.test.fixtures.d.ts +1049 -0
  113. package/dist-tsc/view-config-utils.test.fixtures.d.ts.map +1 -0
  114. package/dist-tsc/view-config-utils.test.fixtures.js +883 -0
  115. package/dist-tsc/view-config-utils.test.js +210 -0
  116. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.d.ts +8 -0
  117. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.d.ts.map +1 -0
  118. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.js +114 -0
  119. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.d.ts +2 -0
  120. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.d.ts.map +1 -0
  121. package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.js +48 -0
  122. package/dist-tsc/vitessce-grid-layout/index.d.ts +2 -0
  123. package/dist-tsc/vitessce-grid-layout/index.d.ts.map +1 -0
  124. package/dist-tsc/vitessce-grid-layout/index.js +1 -0
  125. package/dist-tsc/vitessce-grid-layout/layout-utils.d.ts +15 -0
  126. package/dist-tsc/vitessce-grid-layout/layout-utils.d.ts.map +1 -0
  127. package/dist-tsc/vitessce-grid-layout/layout-utils.js +61 -0
  128. package/dist-tsc/vitessce-grid-layout/layout-utils.test.d.ts +2 -0
  129. package/dist-tsc/vitessce-grid-layout/layout-utils.test.d.ts.map +1 -0
  130. package/dist-tsc/vitessce-grid-layout/layout-utils.test.js +149 -0
  131. package/dist-tsc/vitessce-grid-utils.d.ts +13 -0
  132. package/dist-tsc/vitessce-grid-utils.d.ts.map +1 -0
  133. package/dist-tsc/vitessce-grid-utils.js +141 -0
  134. package/package.json +25 -11
  135. package/src/CallbackPublisher.js +7 -11
  136. package/src/LoadingIndicator.js +1 -2
  137. package/src/TitleInfo.js +12 -85
  138. package/src/VitS.js +143 -85
  139. package/src/VitessceGrid.js +35 -21
  140. package/src/VitessceGrid.test.jsx +23 -8
  141. package/src/Warning.js +4 -4
  142. package/src/data/AbstractLoader.js +2 -25
  143. package/src/data/AbstractTwoStepLoader.js +1 -1
  144. package/src/data/LoaderResult.js +5 -0
  145. package/src/data/index.js +3 -3
  146. package/src/data/loader-registry.js +22 -13
  147. package/src/data-hook-utils.js +119 -86
  148. package/src/data-hooks.js +150 -131
  149. package/src/errors/DataSourceFetchError.js +2 -2
  150. package/src/errors/DatasetNotFoundError.js +1 -1
  151. package/src/errors/LoaderNotFoundError.js +1 -1
  152. package/src/errors/LoaderValidationError.js +1 -1
  153. package/src/errors/index.js +5 -6
  154. package/src/hooks.js +81 -26
  155. package/src/index.js +23 -46
  156. package/src/mui-utils.js +52 -0
  157. package/src/shared-mui/components.js +10 -8
  158. package/src/shared-mui/container.js +1 -1
  159. package/src/shared-mui/styles.js +5 -2
  160. package/src/shared-plot-options/CellColorEncodingOption.js +3 -4
  161. package/src/shared-plot-options/OptionSelect.js +3 -3
  162. package/src/shared-plot-options/OptionsContainer.js +2 -5
  163. package/src/shared-plot-options/index.js +4 -4
  164. package/src/shared-plot-options/styles.js +2 -2
  165. package/src/state/hooks.js +75 -23
  166. package/src/title-styles.js +73 -0
  167. package/src/view-config-utils.js +54 -98
  168. package/src/view-config-utils.test.jsx +223 -0
  169. package/src/vitessce-grid-layout/VitessceGridLayout.js +51 -30
  170. package/src/vitessce-grid-layout/VitessceGridLayout.test.jsx +17 -9
  171. package/src/vitessce-grid-layout/index.js +1 -1
  172. package/src/vitessce-grid-layout/layout-utils.js +1 -1
  173. package/src/vitessce-grid-layout/layout-utils.test.js +2 -1
  174. package/src/vitessce-grid-utils.js +27 -15
  175. package/dist/index.mjs +0 -84801
  176. package/src/component-registry.js +0 -21
  177. package/src/errors/OptionsValidationError.js +0 -25
  178. package/src/file-options-schemas-legacy.js +0 -139
  179. package/src/file-options-schemas-legacy.test.js +0 -138
  180. package/src/file-options-schemas.js +0 -327
  181. package/src/file-options-schemas.test.js +0 -26
  182. package/src/joint-file-types-legacy.js +0 -298
  183. package/src/joint-file-types-legacy.test.js +0 -412
  184. package/src/joint-file-types.js +0 -171
  185. package/src/joint-file-types.test.js +0 -144
  186. package/src/json-schemas.js +0 -9
  187. package/src/plugins.js +0 -186
  188. package/src/plugins.test.js +0 -42
  189. package/src/schemas/config-0.1.0.schema.json +0 -85
  190. package/src/schemas/config-1.0.0.schema.json +0 -733
  191. package/src/schemas/config-1.0.1.schema.json +0 -909
  192. package/src/schemas/config-1.0.10.schema.json +0 -969
  193. package/src/schemas/config-1.0.11.schema.json +0 -990
  194. package/src/schemas/config-1.0.12.schema.json +0 -997
  195. package/src/schemas/config-1.0.13.schema.json +0 -1013
  196. package/src/schemas/config-1.0.14.schema.json +0 -1048
  197. package/src/schemas/config-1.0.15.schema.json +0 -1048
  198. package/src/schemas/config-1.0.16.schema.json +0 -1069
  199. package/src/schemas/config-1.0.16.schema.test.js +0 -32
  200. package/src/schemas/config-1.0.2.schema.json +0 -911
  201. package/src/schemas/config-1.0.3.schema.json +0 -911
  202. package/src/schemas/config-1.0.4.schema.json +0 -949
  203. package/src/schemas/config-1.0.5.schema.json +0 -949
  204. package/src/schemas/config-1.0.6.schema.json +0 -950
  205. package/src/schemas/config-1.0.7.schema.json +0 -950
  206. package/src/schemas/config-1.0.8.schema.json +0 -966
  207. package/src/schemas/config-1.0.9.schema.json +0 -965
  208. package/src/schemas/obsSets.schema.js +0 -195
  209. package/src/schemas/obsSetsTabular.schema.js +0 -39
  210. package/src/schemas/raster.schema.js +0 -121
  211. package/src/schemas/schema-schema.sh +0 -34
  212. package/src/schemas/schema.test-old.js +0 -49
  213. package/src/view-config-upgraders.js +0 -628
  214. package/src/view-config-utils.test.js +0 -95
  215. package/src/view-config-versions.js +0 -68
@@ -1,13 +1,16 @@
1
- import { useState, useEffect } from 'react';
2
- import equal from 'fast-deep-equal';
3
- import { capitalize } from '@vitessce/utils';
1
+ import { useEffect, useMemo } from 'react';
2
+ import { capitalize, fromEntries } from '@vitessce/utils';
4
3
  import { STATUS } from '@vitessce/constants-internal';
5
- import { useMatchingLoader, useMatchingLoaders, useSetWarning } from './state/hooks';
4
+ import { useQuery, useQueries } from '@tanstack/react-query';
5
+ import {
6
+ getMatchingLoader,
7
+ useMatchingLoader,
8
+ useSetWarning,
9
+ } from './state/hooks.js';
6
10
  import {
7
11
  AbstractLoaderError,
8
12
  LoaderNotFoundError,
9
- } from './errors/index';
10
- import { getDefaultCoordinationValues } from './plugins';
13
+ } from './errors/index.js';
11
14
 
12
15
  /**
13
16
  * Warn via publishing to the console
@@ -38,12 +41,12 @@ export function initCoordinationSpace(values, setters, initialValues) {
38
41
  if (!values || !setters) {
39
42
  return;
40
43
  }
41
- const defaultCoordinationValues = getDefaultCoordinationValues();
42
44
  Object.entries(values).forEach(([coordinationType, value]) => {
43
45
  const setterName = `set${capitalize(coordinationType)}`;
44
46
  const setterFunc = setters[setterName];
45
47
  const initialValue = initialValues && initialValues[coordinationType];
46
- const shouldInit = equal(initialValue, defaultCoordinationValues[coordinationType]);
48
+ // Interpret null as "uninitialized" and therefore needing initialization.
49
+ const shouldInit = initialValue === null;
47
50
  if (shouldInit && setterFunc) {
48
51
  setterFunc(value);
49
52
  }
@@ -51,6 +54,31 @@ export function initCoordinationSpace(values, setters, initialValues) {
51
54
  }
52
55
 
53
56
 
57
+ async function dataQueryFn(ctx) {
58
+ const { placeholderObject, loaders } = ctx.meta;
59
+ // This ordering of the queryKey must match.
60
+ const [dataset, dataType, matchOn, isRequired] = ctx.queryKey;
61
+ const loader = getMatchingLoader(loaders, dataset, dataType, matchOn);
62
+ if (loader) {
63
+ // TODO: can cacheing logic be removed from all loaders?
64
+ const payload = await loader.load();
65
+ if (!payload) return placeholderObject; // TODO: throw error instead?
66
+ const { data, url, coordinationValues } = payload;
67
+ // Status: success
68
+ // Array of objects like { url, name }.
69
+ const urls = Array.isArray(url) ? url : [{ url, name: dataType }];
70
+ return { data, coordinationValues, urls };
71
+ }
72
+ // No loader was found.
73
+ if (isRequired) {
74
+ // Status: error
75
+ throw new LoaderNotFoundError(loaders, dataset, dataType, matchOn);
76
+ } else {
77
+ // Status: success
78
+ return { data: placeholderObject };
79
+ }
80
+ }
81
+
54
82
  /**
55
83
  * Get data from a cells data type loader,
56
84
  * updating "ready" and URL state appropriately.
@@ -60,8 +88,6 @@ export function initCoordinationSpace(values, setters, initialValues) {
60
88
  * datasets and data types to loader instances.
61
89
  * @param {string} dataset The key for a dataset,
62
90
  * used to identify which loader to use.
63
- * @param {function} addUrl A function to call to update
64
- * the URL list.
65
91
  * @param {boolean} isRequired Should a warning be thrown if
66
92
  * loading is unsuccessful?
67
93
  * @param {object} coordinationSetters Object where
@@ -70,54 +96,50 @@ export function initCoordinationSpace(values, setters, initialValues) {
70
96
  * @param {object} initialCoordinationValues Object where
71
97
  * keys are coordination type names with the prefix 'initialize',
72
98
  * values are initialization preferences as boolean values.
73
- * @returns {array} [cells, cellsCount] where
99
+ * @returns {array} [data, status, urls] where
74
100
  * cells is an object and cellsCount is the
75
101
  * number of items in the cells object.
76
102
  */
77
103
  export function useDataType(
78
- dataType, loaders, dataset, addUrl, isRequired,
104
+ dataType, loaders, dataset, isRequired,
79
105
  coordinationSetters, initialCoordinationValues, matchOn,
80
106
  ) {
81
- const [data, setData] = useState({});
82
- const [status, setStatus] = useState(STATUS.LOADING);
83
-
84
107
  const setWarning = useSetWarning();
85
- const loader = useMatchingLoader(loaders, dataset, dataType, matchOn);
108
+ const placeholderObject = useMemo(() => ({}), []);
109
+ const dataQuery = useQuery({
110
+ // TODO: only enable when loaders has been initialized?
111
+ structuralSharing: false,
112
+ placeholderData: placeholderObject,
113
+ // Include the hook name in the queryKey to prevent the case in which an identical queryKey
114
+ // in a different hook would cause an accidental cache hit.
115
+ queryKey: [dataset, dataType, matchOn, isRequired, 'useDataType'],
116
+ // Query function should return an object
117
+ // { data, dataKey } where dataKey is the loaded gene selection.
118
+ queryFn: dataQueryFn,
119
+ meta: { loaders, placeholderObject },
120
+ });
121
+ const { data, status, isFetching, error } = dataQuery;
122
+ const loadedData = data?.data || placeholderObject;
123
+
124
+ const coordinationValues = data?.coordinationValues;
125
+ const urls = data?.urls;
86
126
 
87
127
  useEffect(() => {
88
- if (loader) {
89
- setStatus(STATUS.LOADING);
90
- loader.load().catch(e => warn(e, setWarning)).then((payload) => {
91
- if (!payload) return;
92
- const { data: payloadData, url, coordinationValues } = payload;
93
- setData(payloadData);
94
- if (Array.isArray(url)) {
95
- url.forEach(([val, name]) => {
96
- addUrl(val, name);
97
- });
98
- } else if (url) {
99
- addUrl(url, dataType);
100
- }
101
- initCoordinationSpace(
102
- coordinationValues,
103
- coordinationSetters,
104
- initialCoordinationValues,
105
- );
106
- setStatus(STATUS.SUCCESS);
107
- });
108
- } else {
109
- setData({});
110
- if (isRequired) {
111
- warn(new LoaderNotFoundError(loaders, dataset, dataType, matchOn), setWarning);
112
- setStatus(STATUS.ERROR);
113
- } else {
114
- setStatus(STATUS.SUCCESS);
115
- }
128
+ initCoordinationSpace(
129
+ coordinationValues,
130
+ coordinationSetters,
131
+ initialCoordinationValues,
132
+ );
133
+ }, [coordinationValues]);
134
+
135
+ useEffect(() => {
136
+ if (error) {
137
+ warn(error, setWarning);
116
138
  }
117
- // eslint-disable-next-line react-hooks/exhaustive-deps
118
- }, [loader]);
139
+ }, [error, setWarning]);
119
140
 
120
- return [data, status];
141
+ const dataStatus = isFetching ? STATUS.LOADING : status;
142
+ return [loadedData, dataStatus, urls];
121
143
  }
122
144
 
123
145
  /**
@@ -129,8 +151,6 @@ export function useDataType(
129
151
  * datasets and data types to loader instances.
130
152
  * @param {string} dataset The key for a dataset,
131
153
  * used to identify which loader to use.
132
- * @param {function} addUrl A function to call to update
133
- * the URL list.
134
154
  * @param {boolean} isRequired Should a warning be thrown if
135
155
  * loading is unsuccessful?
136
156
  * @param {object} coordinationSetters Object where
@@ -144,51 +164,64 @@ export function useDataType(
144
164
  * number of items in the cells object.
145
165
  */
146
166
  export function useDataTypeMulti(
147
- dataType, loaders, dataset, addUrl, isRequired,
167
+ dataType, loaders, dataset, isRequired,
148
168
  coordinationSetters, initialCoordinationValues, matchOnObj,
149
169
  ) {
150
- const [data, setData] = useState({});
151
- const [status, setStatus] = useState(STATUS.LOADING);
152
-
170
+ const placeholderObject = useMemo(() => ({}), []);
153
171
  const setWarning = useSetWarning();
154
- const matchingLoaders = useMatchingLoaders(loaders, dataset, dataType, matchOnObj);
172
+
173
+ const matchOnEntries = matchOnObj ? Object.entries(matchOnObj) : [];
174
+ const dataQueries = useQueries({
175
+ // eslint-disable-next-line no-unused-vars
176
+ queries: matchOnEntries.map(([scopeKey, matchOn]) => ({
177
+ structuralSharing: false,
178
+ placeholderData: placeholderObject,
179
+ // Query key should match useDataType for shared cacheing
180
+ // and correctness of dataQueryFn.
181
+ queryKey: [dataset, dataType, matchOn, isRequired, 'useDataType'],
182
+ // Query function should return an object
183
+ // { data, dataKey } where dataKey is the loaded gene selection.
184
+ queryFn: dataQueryFn,
185
+ meta: { loaders, placeholderObject },
186
+ })),
187
+ });
188
+
189
+ const anyLoading = dataQueries.some(q => q.isFetching);
190
+ const anyError = dataQueries.some(q => q.isError);
191
+ // eslint-disable-next-line no-nested-ternary
192
+ const dataStatus = anyLoading ? STATUS.LOADING : (anyError ? STATUS.ERROR : STATUS.SUCCESS);
193
+ const isSuccess = dataStatus === STATUS.SUCCESS;
155
194
 
156
195
  useEffect(() => {
157
- if (matchingLoaders) {
158
- setStatus(STATUS.LOADING);
159
- Object.entries(matchingLoaders).forEach(([scopeKey, loader]) => {
160
- if (loader) {
161
- loader.load().catch(e => warn(e, setWarning)).then((payload) => {
162
- if (!payload) return;
163
- const { data: payloadData, url, coordinationValues } = payload;
164
- setData((prev) => {
165
- // eslint-disable-next-line no-param-reassign
166
- prev[scopeKey] = payloadData;
167
- return prev;
168
- });
169
- addUrl(url, dataType);
170
- initCoordinationSpace(
171
- coordinationValues,
172
- coordinationSetters,
173
- initialCoordinationValues,
174
- );
175
- setStatus(STATUS.SUCCESS);
176
- });
177
- }
196
+ dataQueries
197
+ .map(q => q.data?.coordinationValues)
198
+ .filter(v => Boolean(v))
199
+ .forEach((coordinationValues) => {
200
+ initCoordinationSpace(
201
+ coordinationValues,
202
+ coordinationSetters,
203
+ initialCoordinationValues,
204
+ );
178
205
  });
179
- } else {
180
- setData({});
181
- if (isRequired) {
182
- warn(new LoaderNotFoundError(loaders, dataset, dataType, matchOnObj), setWarning);
183
- setStatus(STATUS.ERROR);
184
- } else {
185
- setStatus(STATUS.SUCCESS);
186
- }
187
- }
206
+ // Deliberate dependency omissions: use indirect dependencies for efficiency.
188
207
  // eslint-disable-next-line react-hooks/exhaustive-deps
189
- }, [matchingLoaders]);
208
+ }, [isSuccess]);
190
209
 
191
- return [data, status];
210
+ useEffect(() => {
211
+ dataQueries.map(q => q.error).filter(e => Boolean(e)).forEach((error) => {
212
+ warn(error, setWarning);
213
+ });
214
+ // Deliberate dependency omissions: use indirect dependencies for efficiency.
215
+ // eslint-disable-next-line react-hooks/exhaustive-deps
216
+ }, [anyError, setWarning]);
217
+
218
+ // Convert data to object keyed by scopeKey.
219
+ const data = useMemo(() => fromEntries(
220
+ matchOnEntries.map(([scopeKey], i) => ([scopeKey, dataQueries[i].data?.data])),
221
+ // Deliberate dependency omissions: matchOnEntries, since dataQueries depends on it.
222
+ // eslint-disable-next-line react-hooks/exhaustive-deps
223
+ ), [dataQueries]);
224
+ return [data, dataStatus];
192
225
  }
193
226
 
194
227
  export function useHasLoader(loaders, dataset, dataType, matchOn) {