Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions packages/qwik/src/core/shared/qrl/qrl-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type InvokeTuple,
} from '../../use/use-core';
import { getQFuncs, QInstanceAttr } from '../utils/markers';
import { isPromise, maybeThen } from '../utils/promises';
import { isPromise, maybeThen, retryOnPromise } from '../utils/promises';
import { qDev, qSerialize, qTest, seal } from '../utils/qdev';
import { isArray, isFunction, type ValueOrPromise } from '../utils/types';
import type { QRLDev } from './qrl';
Expand Down Expand Up @@ -93,12 +93,14 @@ export const createQRL = <TYPE>(
// Note that we bind the current `this`
const bound = (...args: QrlArgs<TYPE>): ValueOrPromise<QrlReturn<TYPE> | undefined> => {
if (!qrl.resolved) {
return qrl.resolve().then((fn) => {
if (!isFunction(fn)) {
throw qError(QError.qrlIsNotFunction);
}
return bound(...args);
});
return retryOnPromise(() =>
qrl.resolve().then((fn) => {
if (!isFunction(fn)) {
throw qError(QError.qrlIsNotFunction);
}
return bound(...args);
})
);
}
if (beforeFn && beforeFn() === false) {
return;
Expand Down
32 changes: 32 additions & 0 deletions starters/apps/e2e/src/components/qrl/qrl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { $, component$, useComputed$, useSignal } from "@qwik.dev/core";

export const QRL = component$(() => {
return (
<>
<ShouldResolveInnerComputedQRL />
</>
);
});

export const ShouldResolveInnerComputedQRL = component$(() => {
const test = useComputed$(() => 0);
return <InnerComputedButton test={test} />;
});

export const InnerComputedButton = component$<any>((props) => {
const syncSelectionCounter = useSignal(0);
const syncSelection = $(() => {
syncSelectionCounter.value++;
props.test.value;
});

const handleClick = $(() => {
syncSelection();
});

return (
<button id="inner-computed-button" onClick$={handleClick}>
Click Me {syncSelectionCounter.value}
</button>
);
});
2 changes: 2 additions & 0 deletions starters/apps/e2e/src/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { UseId } from "./components/useid/useid";
import { Watch } from "./components/watch/watch";

import "./global.css";
import { QRL } from "./components/qrl/qrl";

const tests: Record<string, FunctionComponent> = {
"/e2e/two-listeners": () => <TwoListeners />,
Expand Down Expand Up @@ -71,6 +72,7 @@ const tests: Record<string, FunctionComponent> = {
"/e2e/build-variables": () => <BuildVariables />,
"/e2e/exception/render": () => <RenderExceptions />,
"/e2e/exception/use-task": () => <UseTaskExceptions />,
"/e2e/qrl": () => <QRL />,
};

export const Root = component$<{ pathname: string }>(({ pathname }) => {
Expand Down
15 changes: 15 additions & 0 deletions starters/e2e/e2e.qrl.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect, test } from "@playwright/test";
test("should update counter without uncaught promises", async ({ page }) => {
await page.goto("/e2e/qrl");
page.on("pageerror", (err) => expect(err).toEqual(undefined));
page.on("console", (msg) => {
if (msg.type() === "error") {
expect(msg.text()).toEqual(undefined);
}
});
const button = page.locator("#inner-computed-button");
await expect(button).toContainText("Click Me 0");

// 先执行点击操作
await button.click();
});
Loading