@teleporthq/teleport-plugin-next-data-source 0.43.46 → 0.43.48
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/__tests__/refetch-loading-state.test.ts +264 -0
- package/dist/cjs/loading-state.d.ts +92 -0
- package/dist/cjs/loading-state.d.ts.map +1 -0
- package/dist/cjs/loading-state.js +186 -0
- package/dist/cjs/loading-state.js.map +1 -0
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +15 -1
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/loading-state.d.ts +92 -0
- package/dist/esm/loading-state.d.ts.map +1 -0
- package/dist/esm/loading-state.js +157 -0
- package/dist/esm/loading-state.js.map +1 -0
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +15 -1
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/loading-state.ts +297 -0
- package/src/pagination-plugin.ts +25 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as types from '@babel/types';
|
|
2
|
+
/**
|
|
3
|
+
* ------------------------------------------------------------------
|
|
4
|
+
* Refetch loading state for array-mapper `DataProvider`s
|
|
5
|
+
* ------------------------------------------------------------------
|
|
6
|
+
*
|
|
7
|
+
* `DataProvider` (from `@teleporthq/react-components`) renders its LOADING
|
|
8
|
+
* slot only when it has no data to show:
|
|
9
|
+
*
|
|
10
|
+
* case "idle":
|
|
11
|
+
* case "loading":
|
|
12
|
+
* return props.persistDataDuringLoading && data
|
|
13
|
+
* ? renderSuccess(data, true)
|
|
14
|
+
* : renderLoading()
|
|
15
|
+
*
|
|
16
|
+
* Every generated array-mapper list ships `persistDataDuringLoading={true}`,
|
|
17
|
+
* and that flag is load-bearing on the FIRST paint: when the page prefetches
|
|
18
|
+
* rows in `getStaticProps` and hands them over as `initialData`, the provider
|
|
19
|
+
* deliberately skips its first client fetch and therefore never leaves the
|
|
20
|
+
* `idle` status. Without the flag that page would render the loading slot
|
|
21
|
+
* forever instead of the prefetched rows.
|
|
22
|
+
*
|
|
23
|
+
* The side effect is that once the provider owns data, EVERY later refetch is
|
|
24
|
+
* invisible: changing the category filter, the sort order or the search term
|
|
25
|
+
* re-runs the query while the stale rows stay on screen, so the buyer gets no
|
|
26
|
+
* feedback until the new rows pop in. (Page changes and search changes also
|
|
27
|
+
* remount the provider through its `key`, which resets `data` — but a filter
|
|
28
|
+
* or sort change keeps the same key, so nothing at all happens visually.)
|
|
29
|
+
*
|
|
30
|
+
* The provider does pass an `isLoading` flag as the second argument of
|
|
31
|
+
* `renderSuccess`, but it is `true` for the `idle` status as well — i.e.
|
|
32
|
+
* permanently true on any page that skipped its first fetch because it had
|
|
33
|
+
* `initialData` — so it cannot be used to decide what to paint.
|
|
34
|
+
*
|
|
35
|
+
* Fix: track the in-flight fetches of each data source in the PAGE component
|
|
36
|
+
* and hand `persistDataDuringLoading` the negated flag. `fetchData` is the one
|
|
37
|
+
* function the generator owns and the provider calls exactly once per fetch, so
|
|
38
|
+
* it is where the flag is raised (`true` when the request starts) and lowered
|
|
39
|
+
* (`false` once it settles, success or failure). While a refetch is in flight
|
|
40
|
+
* `persistDataDuringLoading` is `false`, so the provider falls through to
|
|
41
|
+
* `renderLoading()` and the array mapper's designed loading state shows; when
|
|
42
|
+
* the request settles the flag drops back to `true` and the rows return.
|
|
43
|
+
*
|
|
44
|
+
* Why not branch inside `renderSuccess` instead: the loading JSX would have to
|
|
45
|
+
* be duplicated into the success render prop, and `styled-jsx` only scopes JSX
|
|
46
|
+
* that lives inside the component's returned tree — every workaround that
|
|
47
|
+
* hoists the loading markup into a shared local helper silently loses its
|
|
48
|
+
* `jsx-<hash>` class and therefore all of its styles.
|
|
49
|
+
*
|
|
50
|
+
* Nothing changes for a provider that is idle or mounting: `isFetching` starts
|
|
51
|
+
* at `false`, so the server render and the first client render are identical
|
|
52
|
+
* (no hydration mismatch) and the `initialData` fast path is untouched.
|
|
53
|
+
*/
|
|
54
|
+
export interface LoadingStateVars {
|
|
55
|
+
/** Boolean state: `true` while at least one fetch for this data source is in flight. */
|
|
56
|
+
isFetchingVar: string;
|
|
57
|
+
/** Setter for `isFetchingVar`. */
|
|
58
|
+
setIsFetchingVar: string;
|
|
59
|
+
/**
|
|
60
|
+
* Ref holding the number of fetches currently in flight. A boolean alone is
|
|
61
|
+
* not enough: two controls changed in quick succession (e.g. category then
|
|
62
|
+
* sort) start two overlapping requests, and the first one to settle would
|
|
63
|
+
* otherwise lower the flag while the second is still running — flashing the
|
|
64
|
+
* stale rows back for the rest of the second request.
|
|
65
|
+
*/
|
|
66
|
+
inFlightRefVar: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function getLoadingStateVars(index: number): LoadingStateVars;
|
|
69
|
+
/**
|
|
70
|
+
* `const ds_N_fetchesInFlight = useRef(0)`
|
|
71
|
+
* `const [ds_N_isFetching, setDs_N_isFetching] = useState(false)`
|
|
72
|
+
*
|
|
73
|
+
* Both are stable across renders (a ref object and a `useState` setter), which
|
|
74
|
+
* is what lets the wrapped `fetchData` keep its empty `useCallback` dependency
|
|
75
|
+
* array — a changing `fetchData` identity would retrigger the provider's fetch
|
|
76
|
+
* effect on every render.
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildLoadingStateDeclarations(vars: LoadingStateVars): types.Statement[];
|
|
79
|
+
/**
|
|
80
|
+
* Wires the refetch loading state into a single `DataProvider` JSX element.
|
|
81
|
+
*
|
|
82
|
+
* No-ops (returning `false`, so the caller emits no state declarations) when
|
|
83
|
+
* the provider cannot benefit from it:
|
|
84
|
+
* - no `renderLoading` slot — the array mapper has no loading state designed,
|
|
85
|
+
* so falling through to it would blank the list out instead of showing
|
|
86
|
+
* something; keeping the stale rows is the better of the two.
|
|
87
|
+
* - `fetchData` missing, not memoized, or not an expression-bodied promise
|
|
88
|
+
* chain — see `findMemoizedFetchDataArrow`.
|
|
89
|
+
* - already wired — keeps a second pass over the same AST idempotent.
|
|
90
|
+
*/
|
|
91
|
+
export declare function applyLoadingStateToDataProvider(dataProvider: any, vars: LoadingStateVars): boolean;
|
|
92
|
+
//# sourceMappingURL=loading-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loading-state.d.ts","sourceRoot":"","sources":["../../src/loading-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,wFAAwF;IACxF,aAAa,EAAE,MAAM,CAAA;IACrB,kCAAkC;IAClC,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAMnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,gBAAgB,GAAG,KAAK,CAAC,SAAS,EAAE,CAkBvF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAE7C,YAAY,EAAE,GAAG,EACjB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAyBT"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import * as types from '@babel/types';
|
|
2
|
+
export function getLoadingStateVars(index) {
|
|
3
|
+
return {
|
|
4
|
+
isFetchingVar: "ds_".concat(index, "_isFetching"),
|
|
5
|
+
setIsFetchingVar: "setDs_".concat(index, "_isFetching"),
|
|
6
|
+
inFlightRefVar: "ds_".concat(index, "_fetchesInFlight"),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `const ds_N_fetchesInFlight = useRef(0)`
|
|
11
|
+
* `const [ds_N_isFetching, setDs_N_isFetching] = useState(false)`
|
|
12
|
+
*
|
|
13
|
+
* Both are stable across renders (a ref object and a `useState` setter), which
|
|
14
|
+
* is what lets the wrapped `fetchData` keep its empty `useCallback` dependency
|
|
15
|
+
* array — a changing `fetchData` identity would retrigger the provider's fetch
|
|
16
|
+
* effect on every render.
|
|
17
|
+
*/
|
|
18
|
+
export function buildLoadingStateDeclarations(vars) {
|
|
19
|
+
return [
|
|
20
|
+
types.variableDeclaration('const', [
|
|
21
|
+
types.variableDeclarator(types.identifier(vars.inFlightRefVar), types.callExpression(types.identifier('useRef'), [types.numericLiteral(0)])),
|
|
22
|
+
]),
|
|
23
|
+
types.variableDeclaration('const', [
|
|
24
|
+
types.variableDeclarator(types.arrayPattern([
|
|
25
|
+
types.identifier(vars.isFetchingVar),
|
|
26
|
+
types.identifier(vars.setIsFetchingVar),
|
|
27
|
+
]), types.callExpression(types.identifier('useState'), [types.booleanLiteral(false)])),
|
|
28
|
+
]),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Wires the refetch loading state into a single `DataProvider` JSX element.
|
|
33
|
+
*
|
|
34
|
+
* No-ops (returning `false`, so the caller emits no state declarations) when
|
|
35
|
+
* the provider cannot benefit from it:
|
|
36
|
+
* - no `renderLoading` slot — the array mapper has no loading state designed,
|
|
37
|
+
* so falling through to it would blank the list out instead of showing
|
|
38
|
+
* something; keeping the stale rows is the better of the two.
|
|
39
|
+
* - `fetchData` missing, not memoized, or not an expression-bodied promise
|
|
40
|
+
* chain — see `findMemoizedFetchDataArrow`.
|
|
41
|
+
* - already wired — keeps a second pass over the same AST idempotent.
|
|
42
|
+
*/
|
|
43
|
+
export function applyLoadingStateToDataProvider(
|
|
44
|
+
// tslint:disable-next-line:no-any
|
|
45
|
+
dataProvider, vars) {
|
|
46
|
+
var _a;
|
|
47
|
+
var attributes = (_a = dataProvider === null || dataProvider === void 0 ? void 0 : dataProvider.openingElement) === null || _a === void 0 ? void 0 : _a.attributes;
|
|
48
|
+
if (!Array.isArray(attributes)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (!findAttribute(attributes, 'renderLoading')) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
var fetchDataAttr = findAttribute(attributes, 'fetchData');
|
|
55
|
+
if (!fetchDataAttr) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
var fetchArrow = findMemoizedFetchDataArrow(fetchDataAttr);
|
|
59
|
+
if (!fetchArrow || fetchArrow.body.type !== 'CallExpression') {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
fetchArrow.body = buildTrackedFetchBody(fetchArrow.body, vars);
|
|
63
|
+
setPersistDataDuringLoading(attributes, vars);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
// tslint:disable-next-line:no-any
|
|
67
|
+
function findAttribute(attributes, name) {
|
|
68
|
+
return attributes.find(
|
|
69
|
+
// tslint:disable-next-line:no-any
|
|
70
|
+
function (attr) { var _a; return (attr === null || attr === void 0 ? void 0 : attr.type) === 'JSXAttribute' && ((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name) === name; });
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The `useCallback(fn, [])`-wrapped arrow behind a `fetchData` attribute, or
|
|
74
|
+
* `undefined` when the value has any other shape.
|
|
75
|
+
*
|
|
76
|
+
* Requiring the memoized form is a safety condition, not a convenience.
|
|
77
|
+
* `DataProvider` refetches whenever the `fetchData` identity changes
|
|
78
|
+
* (`useEffect(..., [params, fetchData])`), so wrapping a fetcher that is
|
|
79
|
+
* re-created on every render with something that sets state would build a
|
|
80
|
+
* self-sustaining loop: fetch → setState → render → new fetcher identity →
|
|
81
|
+
* fetch. The array-mapper providers this plugin owns are always memoized; the
|
|
82
|
+
* few unmemoized `fetchData` values other plugins emit are left exactly as they
|
|
83
|
+
* are today.
|
|
84
|
+
*/
|
|
85
|
+
function findMemoizedFetchDataArrow(attribute) {
|
|
86
|
+
var _a;
|
|
87
|
+
var value = attribute.value;
|
|
88
|
+
if (!value || value.type !== 'JSXExpressionContainer') {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
var expression = value.expression;
|
|
92
|
+
if (expression.type !== 'CallExpression' ||
|
|
93
|
+
expression.callee.type !== 'Identifier' ||
|
|
94
|
+
expression.callee.name !== 'useCallback' ||
|
|
95
|
+
((_a = expression.arguments[0]) === null || _a === void 0 ? void 0 : _a.type) !== 'ArrowFunctionExpression') {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return expression.arguments[0];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Turns `(params) => fetch(...).then(...)` into
|
|
102
|
+
*
|
|
103
|
+
* (params) => {
|
|
104
|
+
* ds_N_fetchesInFlight.current += 1
|
|
105
|
+
* setDs_N_isFetching(true)
|
|
106
|
+
* return fetch(...).then(...).finally(() => {
|
|
107
|
+
* ds_N_fetchesInFlight.current -= 1
|
|
108
|
+
* if (ds_N_fetchesInFlight.current <= 0) {
|
|
109
|
+
* ds_N_fetchesInFlight.current = 0
|
|
110
|
+
* setDs_N_isFetching(false)
|
|
111
|
+
* }
|
|
112
|
+
* })
|
|
113
|
+
* }
|
|
114
|
+
*
|
|
115
|
+
* `finally` (rather than a `then` pair) keeps the flag honest when the request
|
|
116
|
+
* rejects: the provider switches to its error status and the loading state must
|
|
117
|
+
* not stay on screen. The counter is clamped at 0 so a late settle from a
|
|
118
|
+
* provider instance that was remounted through its `key` can never drive it
|
|
119
|
+
* negative and wedge the flag on.
|
|
120
|
+
*
|
|
121
|
+
* `fetchExpression` is the `fetch(...).then(...).then(...)` chain the generator
|
|
122
|
+
* emitted, so `.finally` is always available on it — the caller only reaches
|
|
123
|
+
* here for a call-expression body.
|
|
124
|
+
*/
|
|
125
|
+
function buildTrackedFetchBody(fetchExpression, vars) {
|
|
126
|
+
var inFlightCount = types.memberExpression(types.identifier(vars.inFlightRefVar), types.identifier('current'));
|
|
127
|
+
var settleHandler = types.arrowFunctionExpression([], types.blockStatement([
|
|
128
|
+
types.expressionStatement(types.assignmentExpression('-=', types.cloneNode(inFlightCount, true), types.numericLiteral(1))),
|
|
129
|
+
types.ifStatement(types.binaryExpression('<=', types.cloneNode(inFlightCount, true), types.numericLiteral(0)), types.blockStatement([
|
|
130
|
+
types.expressionStatement(types.assignmentExpression('=', types.cloneNode(inFlightCount, true), types.numericLiteral(0))),
|
|
131
|
+
types.expressionStatement(types.callExpression(types.identifier(vars.setIsFetchingVar), [
|
|
132
|
+
types.booleanLiteral(false),
|
|
133
|
+
])),
|
|
134
|
+
])),
|
|
135
|
+
]));
|
|
136
|
+
return types.blockStatement([
|
|
137
|
+
types.expressionStatement(types.assignmentExpression('+=', types.cloneNode(inFlightCount, true), types.numericLiteral(1))),
|
|
138
|
+
types.expressionStatement(types.callExpression(types.identifier(vars.setIsFetchingVar), [types.booleanLiteral(true)])),
|
|
139
|
+
types.returnStatement(types.callExpression(types.memberExpression(fetchExpression, types.identifier('finally')), [
|
|
140
|
+
settleHandler,
|
|
141
|
+
])),
|
|
142
|
+
]);
|
|
143
|
+
}
|
|
144
|
+
/** `persistDataDuringLoading={!ds_N_isFetching}`, replacing any existing value. */
|
|
145
|
+
// tslint:disable-next-line:no-any
|
|
146
|
+
function setPersistDataDuringLoading(attributes, vars) {
|
|
147
|
+
var attribute = types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.unaryExpression('!', types.identifier(vars.isFetchingVar), true)));
|
|
148
|
+
var existingIndex = attributes.findIndex(
|
|
149
|
+
// tslint:disable-next-line:no-any
|
|
150
|
+
function (attr) { var _a; return (attr === null || attr === void 0 ? void 0 : attr.type) === 'JSXAttribute' && ((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name) === 'persistDataDuringLoading'; });
|
|
151
|
+
if (existingIndex === -1) {
|
|
152
|
+
attributes.push(attribute);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
attributes[existingIndex] = attribute;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=loading-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loading-state.js","sourceRoot":"","sources":["../../src/loading-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-plugin.d.ts","sourceRoot":"","sources":["../../src/pagination-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,EAIvB,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"pagination-plugin.d.ts","sourceRoot":"","sources":["../../src/pagination-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,EAIvB,MAAM,4BAA4B,CAAA;AA+tBnC,eAAO,MAAM,qCAAqC,EAAE,sBAAsB,CAAC,EAAE,CAy3B5E,CAAA"}
|
|
@@ -43,6 +43,7 @@ import { generateSafeFileName } from './utils';
|
|
|
43
43
|
import { generateDataSourceFetcherWithCore } from './data-source-fetchers';
|
|
44
44
|
import { appendSortsParam, extractDynamicSort } from './sort-utils';
|
|
45
45
|
import { appendFiltersParam, pushStateIdsAsDeps, pushPropIdsAsDeps } from './filter-utils';
|
|
46
|
+
import { applyLoadingStateToDataProvider, buildLoadingStateDeclarations, getLoadingStateVars, } from './loading-state';
|
|
46
47
|
// tslint:disable-next-line:no-any
|
|
47
48
|
function parseSearchDefaultValue(raw) {
|
|
48
49
|
if (!raw || typeof raw !== 'object') {
|
|
@@ -551,7 +552,7 @@ function pushSearchUrlSyncEffects(effectStatements, usage, vars) {
|
|
|
551
552
|
// ==================== MAIN PLUGIN ====================
|
|
552
553
|
export var createNextArrayMapperPaginationPlugin = function () {
|
|
553
554
|
var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
|
|
554
|
-
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, needsUseRouter, hasRouterDecl, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages, paginationNodes, paginatedUsages;
|
|
555
|
+
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, needsUseRouter, hasRouterDecl, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, loadingStateDeclarations, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages, paginationNodes, paginatedUsages;
|
|
555
556
|
var _a;
|
|
556
557
|
return __generator(this, function (_b) {
|
|
557
558
|
uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
|
|
@@ -914,6 +915,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
914
915
|
return hasRepeater;
|
|
915
916
|
});
|
|
916
917
|
usageIndexByDataSourceId = new Map();
|
|
918
|
+
loadingStateDeclarations = [];
|
|
917
919
|
dataProvidersWithRepeaters.forEach(function (dp) {
|
|
918
920
|
var _a, _b, _c;
|
|
919
921
|
var nameAttr = dp.openingElement.attributes.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'name'; });
|
|
@@ -944,9 +946,21 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
944
946
|
else if (usage.category === 'plain') {
|
|
945
947
|
updateDataProviderForPlain(dp, fileName, usage);
|
|
946
948
|
}
|
|
949
|
+
// Show the array mapper's loading state while a category/sort/search
|
|
950
|
+
// change refetches, instead of leaving the previous rows on screen with
|
|
951
|
+
// no feedback. Runs last so it sees the `fetchData` and
|
|
952
|
+
// `persistDataDuringLoading` attributes the updaters above just wrote.
|
|
953
|
+
var loadingVars = getLoadingStateVars(usage.index);
|
|
954
|
+
if (applyLoadingStateToDataProvider(dp, loadingVars)) {
|
|
955
|
+
loadingStateDeclarations.push.apply(loadingStateDeclarations, buildLoadingStateDeclarations(loadingVars));
|
|
956
|
+
}
|
|
947
957
|
// Create API route for all categories (including 'plain' for components)
|
|
948
958
|
ensureAPIRouteExists(options.extractedResources, usage, options.dataSources, (_c = options.ecommerceSettings) === null || _c === void 0 ? void 0 : _c.categories);
|
|
949
959
|
});
|
|
960
|
+
// Declare the loading-state hooks alongside the other data-source state, at
|
|
961
|
+
// the top of the component body. Unconditional and in a fixed order, so the
|
|
962
|
+
// hook order stays stable across renders.
|
|
963
|
+
loadingStateDeclarations.reverse().forEach(function (s) { return blockStatement.body.unshift(s); });
|
|
950
964
|
dataProvidersWithoutRepeaters = dataProviders.filter(function (dp) {
|
|
951
965
|
var hasRepeater = findArrayMapperRenderPropInDataProvider(dp) !== undefined;
|
|
952
966
|
return !hasRepeater;
|