Skip to content

Commit f19e7bb

Browse files
Varixowmertens
authored andcommitted
fix: handle head action changes
1 parent cfba19d commit f19e7bb

File tree

5 files changed

+61
-35
lines changed

5 files changed

+61
-35
lines changed

packages/qwik-router/src/runtime/src/head.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
import { withLocale } from '@qwik.dev/core';
1+
import { untrack, withLocale } from '@qwik.dev/core';
2+
import { _retryOnPromise } from '@qwik.dev/core/internal';
23
import type {
34
ContentModule,
45
RouteLocation,
5-
EndpointResponse,
66
ResolvedDocumentHead,
77
DocumentHeadProps,
88
DocumentHeadValue,
9-
ClientPageData,
109
LoaderInternal,
1110
Editable,
1211
ResolveSyncValue,
1312
ActionInternal,
13+
LoaderSignal,
14+
ClientActionData,
1415
} from './types';
1516
import { isPromise } from './utils';
1617

17-
export const resolveHead = (
18-
endpoint: EndpointResponse | ClientPageData,
18+
export const resolveHead = async (
19+
loaderState: Record<string, LoaderSignal<unknown>>,
20+
action: ClientActionData | undefined,
1921
routeLocation: RouteLocation,
2022
contentModules: ContentModule[],
2123
locale: string,
@@ -25,13 +27,19 @@ export const resolveHead = (
2527
const getData = ((loaderOrAction: LoaderInternal | ActionInternal) => {
2628
const id = loaderOrAction.__id;
2729
if (loaderOrAction.__brand === 'server_loader') {
28-
if (!(id in endpoint.loaders)) {
30+
if (!(id in loaderState)) {
2931
throw new Error(
3032
'You can not get the returned data of a loader that has not been executed for this request.'
3133
);
3234
}
35+
} else if (
36+
action &&
37+
action.id === loaderOrAction.__id &&
38+
loaderOrAction.__brand === 'server_action'
39+
) {
40+
return action.data;
3341
}
34-
const data = endpoint.loaders[id];
42+
const data = untrack(() => loaderState[id]?.value);
3543
if (isPromise(data)) {
3644
throw new Error('Loaders returning a promise can not be resolved for the head function.');
3745
}
@@ -48,9 +56,10 @@ export const resolveHead = (
4856
const contentModuleHead = contentModules[i] && contentModules[i].head;
4957
if (contentModuleHead) {
5058
if (typeof contentModuleHead === 'function') {
59+
const contentModuleHeadResult = await _retryOnPromise(() => contentModuleHead(headProps));
5160
resolveDocumentHead(
5261
head,
53-
withLocale(locale, () => contentModuleHead(headProps))
62+
withLocale(locale, () => contentModuleHeadResult)
5463
);
5564
} else if (typeof contentModuleHead === 'object') {
5665
resolveDocumentHead(head, contentModuleHead);

packages/qwik-router/src/runtime/src/qwik-router-component.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,14 @@ export const useQwikRouter = (props?: QwikRouterProps) => {
493493
(routeInternal as any).untrackedValue = { type: navType, dest: trackUrl };
494494

495495
// Needs to be done after routeLocation is updated
496-
const resolvedHead = resolveHead(
497-
clientPageData!,
496+
const resolvedHead = await resolveHead(
497+
loaderState,
498+
clientPageData?.action,
499+
498500
routeLocation,
501+
499502
contentModules,
503+
500504
locale,
501505
serverHead
502506
);
@@ -554,6 +558,12 @@ export const useQwikRouter = (props?: QwikRouterProps) => {
554558
signal.invalidate();
555559
}
556560
}
561+
// remove not existing loaders
562+
for (const key of Object.keys(loaderState)) {
563+
if (!(key in loadersObject)) {
564+
delete loaderState[key];
565+
}
566+
}
557567
}
558568

559569
const win = window as ClientSPAWindow;

packages/qwik/src/core/internal.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,67 +11,67 @@ export type {
1111
QDocument as _QDocument,
1212
VNodeFlags as _VNodeFlags,
1313
} from './client/types';
14+
export {
15+
mapApp_findIndx as _mapApp_findIndx,
16+
mapArray_get as _mapArray_get,
17+
mapArray_set as _mapArray_set,
18+
} from './client/util-mapArray';
19+
export {
20+
vnode_ensureElementInflated as _vnode_ensureElementInflated,
21+
vnode_getAttrKeys as _vnode_getAttrKeys,
22+
vnode_getFirstChild as _vnode_getFirstChild,
23+
vnode_getProps as _vnode_getProps,
24+
vnode_isMaterialized as _vnode_isMaterialized,
25+
vnode_isTextVNode as _vnode_isTextVNode,
26+
vnode_isVirtualVNode as _vnode_isVirtualVNode,
27+
vnode_toString as _vnode_toString,
28+
} from './client/vnode';
1429
export type {
1530
ElementVNode as _ElementVNode,
1631
TextVNode as _TextVNode,
1732
VirtualVNode as _VirtualVNode,
1833
VNode as _VNode,
1934
} from './client/vnode-impl';
20-
export {
21-
vnode_toString as _vnode_toString,
22-
vnode_getProps as _vnode_getProps,
23-
vnode_isTextVNode as _vnode_isTextVNode,
24-
vnode_isVirtualVNode as _vnode_isVirtualVNode,
25-
vnode_getFirstChild as _vnode_getFirstChild,
26-
vnode_isMaterialized as _vnode_isMaterialized,
27-
vnode_ensureElementInflated as _vnode_ensureElementInflated,
28-
vnode_getAttrKeys as _vnode_getAttrKeys,
29-
} from './client/vnode';
30-
export {
31-
mapApp_findIndx as _mapApp_findIndx,
32-
mapArray_get as _mapArray_get,
33-
mapArray_set as _mapArray_set,
34-
} from './client/util-mapArray';
3535

36+
export { _hasStoreEffects, isStore as _isStore } from './reactive-primitives/impl/store';
3637
export { _wrapProp, _wrapSignal } from './reactive-primitives/internal-api';
3738
export { SubscriptionData as _SubscriptionData } from './reactive-primitives/subscription-data';
3839
export { _EFFECT_BACK_REF } from './reactive-primitives/types';
39-
export { _hasStoreEffects } from './reactive-primitives/impl/store';
4040
export {
4141
isStringifiable as _isStringifiable,
4242
type Stringifiable as _Stringifiable,
4343
} from './shared-types';
4444
export {
45+
_getConstProps,
46+
_getVarProps,
4547
isJSXNode as _isJSXNode,
4648
_jsxC,
4749
_jsxQ,
4850
_jsxS,
4951
_jsxSorted,
5052
_jsxSplit,
51-
_getVarProps,
52-
_getConstProps,
5353
} from './shared/jsx/jsx-runtime';
5454
export { _fnSignal } from './shared/qrl/inlined-fn';
55-
export { _SharedContainer } from './shared/shared-container';
5655
export {
5756
_deserialize,
5857
dumpState as _dumpState,
5958
preprocessState as _preprocessState,
6059
_serializationWeakRef,
6160
_serialize,
6261
} from './shared/serdes/index';
63-
export { _CONST_PROPS, _IMMUTABLE, _VAR_PROPS, _UNINITIALIZED } from './shared/utils/constants';
62+
export { _SharedContainer } from './shared/shared-container';
63+
export { _CONST_PROPS, _IMMUTABLE, _UNINITIALIZED, _VAR_PROPS } from './shared/utils/constants';
6464
export { EMPTY_ARRAY as _EMPTY_ARRAY } from './shared/utils/flyweight';
65+
export { retryOnPromise as _retryOnPromise } from './shared/utils/promises';
6566
export { _restProps } from './shared/utils/prop';
6667
export { verifySerializable as _verifySerializable } from './shared/utils/serialize-utils';
6768
export { _walkJSX } from './ssr/ssr-render-jsx';
69+
export { _resolveContextWithoutSequentialScope } from './use/use-context';
6870
export {
71+
_getContextContainer,
6972
_getContextElement,
7073
_getContextEvent,
71-
_getContextContainer,
7274
_jsxBranch,
7375
_waitUntilRendered,
7476
} from './use/use-core';
75-
export { scheduleTask as _task, isTask as _isTask } from './use/use-task';
76-
export { isStore as _isStore } from './reactive-primitives/impl/store';
77-
export { _resolveContextWithoutSequentialScope } from './use/use-context';
77+
export { isTask as _isTask, scheduleTask as _task } from './use/use-task';

packages/qwik/src/core/qwik.core.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,9 @@ export type ResourceReturn<T> = ResourcePending<T> | ResourceResolved<T> | Resou
894894
// @internal (undocumented)
895895
export const _restProps: (props: PropsProxy, omit?: string[], target?: Props) => Props;
896896

897+
// @internal
898+
export function _retryOnPromise<T>(fn: () => ValueOrPromise<T>, retryCount?: number): ValueOrPromise<T>;
899+
897900
// @internal
898901
export const _run: (...args: unknown[]) => ValueOrPromise<unknown>;
899902

packages/qwik/src/core/shared/utils/promises.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ export const delay = (timeout: number) => {
9696
});
9797
};
9898

99-
/** Retries a function that throws a promise. */
99+
/**
100+
* Retries a function that throws a promise.
101+
*
102+
* @internal
103+
*/
100104
export function retryOnPromise<T>(
101105
fn: () => ValueOrPromise<T>,
102106
retryCount: number = 0

0 commit comments

Comments
 (0)