Skip to content

Commit 91a566f

Browse files
authored
refactor: sync render and useStore() not recursive (#618)
1 parent 25d3324 commit 91a566f

File tree

43 files changed

+742
-1258
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+742
-1258
lines changed

packages/docs/src/components/content-nav/content-nav.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { component$, Host, useScopedStyles$ } from '@builder.io/qwik';
33
import styles from './content-nav.css?inline';
44

55
export const ContentNav = component$(
6-
async () => {
6+
() => {
77
useScopedStyles$(styles);
88

99
const page = usePage();

packages/docs/src/components/repl/repl.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { getReplVersion } from './repl-version';
1818
import { updateReplOutput } from './repl-output-update';
1919
import replServerUrl from '@repl-server-url';
2020

21-
export const Repl = component$(async (props: ReplProps) => {
21+
export const Repl = component$((props: ReplProps) => {
2222
useScopedStyles$(styles);
2323

2424
const input = props.input;

packages/docs/src/layouts/builder/builder.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { useLocation } from '../../utils/useLocation';
33
import { Header } from '../../components/header/header';
44
import styles from './builder.css?inline';
55

6-
export const Builder = component$(async () => {
6+
export const Builder = component$(() => {
77
useStyles$(styles);
88
const loc = useLocation();
9-
const html = await fetchQwikBuilderContent(loc.pathname);
9+
const promise = fetchQwikBuilderContent(loc.pathname);
1010
return (
1111
<Host>
1212
<Header />
13-
{html && <main class="builder" dangerouslySetInnerHTML={html} />}
13+
{promise.then((html) => html && <main class="builder" dangerouslySetInnerHTML={html} />)}
1414
</Host>
1515
);
1616
});

packages/qwik/src/core/api.md

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,14 @@ export const component$: <PROPS extends {}>(onMount: OnRenderFn<PROPS>, options?
6868
// @public (undocumented)
6969
export type Component<PROPS extends {}> = FunctionComponent<PublicProps<PROPS>>;
7070

71-
// @public (undocumented)
72-
export type ComponentChild = JSXNode<any> | object | string | number | bigint | boolean | null | undefined;
73-
74-
// @public (undocumented)
75-
export type ComponentChildren = ComponentChild[] | ComponentChild;
76-
7771
// @alpha (undocumented)
7872
export interface ComponentCtx {
7973
// (undocumented)
8074
$hostElement$: Element;
75+
// Warning: (ae-forgotten-export) The symbol "ProcessedJSXNode" needs to be exported by the entry point index.d.ts
76+
//
8177
// (undocumented)
82-
$slots$: JSXNode[];
78+
$slots$: ProcessedJSXNode[];
8379
// (undocumented)
8480
$styleClass$: string | undefined;
8581
// (undocumented)
@@ -323,22 +319,13 @@ export { jsx }
323319
export { jsx as jsxDEV }
324320
export { jsx as jsxs }
325321

326-
// @public (undocumented)
327-
export type JSXFactory<T, PROPS extends {} = any> = (props: PROPS, state?: any) => JSXNode<T>;
328-
329322
// @public (undocumented)
330323
export interface JSXNode<T = any> {
331324
// (undocumented)
332-
children: JSXNode[];
333-
// (undocumented)
334-
elm?: Node;
335-
// (undocumented)
336-
key: string | null;
325+
key: string | number | null;
337326
// (undocumented)
338327
props: Record<string, any> | null;
339328
// (undocumented)
340-
text?: string;
341-
// (undocumented)
342329
type: T;
343330
}
344331

@@ -361,7 +348,7 @@ export type On$Props<T extends {}> = {
361348
};
362349

363350
// @public (undocumented)
364-
export type OnRenderFn<PROPS> = (props: PROPS) => ValueOrPromise<JSXNode<any> | null | (() => JSXNode<any>)>;
351+
export type OnRenderFn<PROPS> = (props: PROPS) => JSXNode<any> | null | (() => JSXNode<any>);
365352

366353
// @alpha
367354
export const pauseContainer: (elmOrDoc: Element | Document) => SnapshotResult;
@@ -447,11 +434,6 @@ export interface Ref<T> {
447434
// @alpha
448435
export const render: (parent: Element | Document, jsxNode: JSXNode<unknown> | FunctionComponent<any>) => Promise<void>;
449436

450-
// @public (undocumented)
451-
export type RenderableProps<P, RefType = any> = P & Readonly<{
452-
children?: ComponentChildren;
453-
}>;
454-
455437
// @alpha (undocumented)
456438
export type ServerFn = () => ValueOrPromise<void | (() => void)>;
457439

@@ -499,9 +481,6 @@ export interface Tracker {
499481
<T extends {}, B extends keyof T>(obj: T, prop: B): T[B];
500482
}
501483

502-
// @alpha (undocumented)
503-
export const unwrapSubscriber: <T extends {}>(obj: T) => any;
504-
505484
// @alpha
506485
export const useCleanup$: (first: () => void) => void;
507486

@@ -603,8 +582,10 @@ export const useServerMount$: (first: ServerFn) => void;
603582
// @public
604583
export const useServerMountQrl: (mountQrl: QRL<ServerFn>) => void;
605584

585+
// Warning: (ae-forgotten-export) The symbol "UseStoreOptions" needs to be exported by the entry point index.d.ts
586+
//
606587
// @public
607-
export const useStore: <STATE extends object>(initialState: STATE | (() => STATE)) => STATE;
588+
export const useStore: <STATE extends object>(initialState: STATE | (() => STATE), opts?: UseStoreOptions) => STATE;
608589

609590
// @public
610591
export const useStyles$: (first: string) => void;
@@ -636,9 +617,6 @@ export const version: string;
636617
// @alpha (undocumented)
637618
export type WatchFn = (track: Tracker) => ValueOrPromise<void | (() => void)>;
638619

639-
// @alpha (undocumented)
640-
export const wrapSubscriber: <T extends {}>(obj: T, subscriber: Subscriber) => any;
641-
642620
// (No @packageDocumentation comment for this package)
643621

644622
```

packages/qwik/src/core/component/component.public.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { $, QRL } from '../import/qrl.public';
22
import type { JSXNode } from '../render/jsx/types/jsx-node';
33
import { OnRenderProp } from '../util/markers';
44
import type { ComponentBaseProps } from '../render/jsx/types/jsx-qwik-attributes';
5-
import type { ValueOrPromise } from '../util/types';
65
import type { FunctionComponent } from '../render/jsx/types/jsx-node';
76
import { jsx } from '../render/jsx/jsx-runtime';
87
import type { MutableWrapper } from '../object/q-object';
@@ -196,9 +195,7 @@ export const component$ = <PROPS extends {}>(
196195
/**
197196
* @public
198197
*/
199-
export type OnRenderFn<PROPS> = (
200-
props: PROPS
201-
) => ValueOrPromise<JSXNode<any> | null | (() => JSXNode<any>)>;
198+
export type OnRenderFn<PROPS> = (props: PROPS) => JSXNode<any> | null | (() => JSXNode<any>);
202199

203200
export interface RenderFactoryOutput<PROPS> {
204201
renderQRL: QRL<OnRenderFn<PROPS>>;

packages/qwik/src/core/component/component.unit.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('q-component', () => {
1111
const fixture = new ElementFixture();
1212
await render(fixture.host, <HelloWorld></HelloWorld>);
1313
const Div = 'div' as any;
14-
expectDOM(
14+
await expectDOM(
1515
fixture.host,
1616
<host>
1717
<Div q:host="">
@@ -24,7 +24,7 @@ describe('q-component', () => {
2424
it('should render Counter and accept events', async () => {
2525
const fixture = new ElementFixture();
2626
await render(fixture.host, <MyCounter step={5} value={15} />);
27-
expectDOM(
27+
await expectDOM(
2828
fixture.host,
2929
<host>
3030
<my-counter>
@@ -37,7 +37,7 @@ describe('q-component', () => {
3737
</host>
3838
);
3939
await trigger(fixture.host, 'button.decrement', 'click');
40-
expectDOM(
40+
await expectDOM(
4141
fixture.host,
4242
<host>
4343
<my-counter>
@@ -67,7 +67,7 @@ describe('q-component', () => {
6767
};
6868
await render(host, <Items items={items} />);
6969
await delay(0);
70-
expectDOM(
70+
await expectDOM(
7171
host,
7272
<host>
7373
<items>

packages/qwik/src/core/error/error.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const QError_useMethodOutsideContext = 14;
1818
export const QError_missingRenderCtx = 15;
1919
export const QError_missingDoc = 16;
2020
export const QError_immutableProps = 17;
21+
export const QError_hostCanOnlyBeAtRoot = 18;
2122

2223
export const qError = (code: number, ...parts: any[]): Error => {
2324
const text = codeToText(code);
@@ -29,23 +30,25 @@ export const qError = (code: number, ...parts: any[]): Error => {
2930
export const codeToText = (code: number): string => {
3031
if (qDev) {
3132
const MAP = [
32-
'Can not serialize a HTML Node that is not an Element',
33-
'Rruntime but no instance found on element.',
34-
'Only primitive and object literals can be serialized',
35-
'Crash while rendering',
36-
'You can render over a existing q:container. Skipping render().',
37-
'Set property',
38-
"Only function's and 'string's are supported.",
39-
"Only objects can be wrapped in 'QObject'",
40-
`Only objects literals can be wrapped in 'QObject'`,
41-
'QRL is not a function',
42-
'Dynamic import not found',
43-
'Unknown type argument',
44-
'not found state for useContext',
45-
"Q-ERROR: invoking 'use*()' method outside of invocation context.",
46-
'Cant access renderCtx for existing context',
47-
'Cant access document for existing context',
48-
'props are inmutable',
33+
'Error while serializing class attribute', // 0
34+
'Can not serialize a HTML Node that is not an Element', // 1
35+
'Rruntime but no instance found on element.', // 2
36+
'Only primitive and object literals can be serialized', // 3
37+
'Crash while rendering', // 4
38+
'You can render over a existing q:container. Skipping render().', // 5
39+
'Set property', // 6
40+
"Only function's and 'string's are supported.", // 7
41+
"Only objects can be wrapped in 'QObject'", // 8
42+
`Only objects literals can be wrapped in 'QObject'`, // 9
43+
'QRL is not a function', // 10
44+
'Dynamic import not found', // 11
45+
'Unknown type argument', // 12
46+
'not found state for useContext', // 13
47+
"Invoking 'use*()' method outside of invocation context.", // 14
48+
'Cant access renderCtx for existing context', // 15
49+
'Cant access document for existing context', // 16
50+
'props are inmutable', // 17
51+
'<Host> component can only be used at the root of a Qwik component$()', // 18
4952
];
5053
return `Code(${code}): ${MAP[code] ?? ''}`;
5154
} else {

packages/qwik/src/core/import/qrl.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { getDocument } from '../util/dom';
77
import { logError } from '../util/log';
88
import { then } from '../util/promises';
99
import { getPlatform } from '../platform/platform';
10-
import { unwrapSubscriber } from '../use/use-subscriber';
1110
import { tryGetInvokeContext } from '../use/use-core';
1211
import {
1312
codeToText,
@@ -18,8 +17,7 @@ import {
1817
QError_unknownTypeArgument,
1918
} from '../error/error';
2019
import { qDev } from '../util/qdev';
21-
import { getProxyTarget } from '../object/store';
22-
import { verifySerializable } from '../object/q-object';
20+
import { getProxyTarget, verifySerializable } from '../object/q-object';
2321

2422
let runtimeSymbolId = 0;
2523
const RUNTIME_QRL = '/runtimeQRL';
@@ -157,7 +155,6 @@ export const inlinedQrl = <T>(
157155
const unwrapLexicalScope = (lexicalScope: any[] | null) => {
158156
if (isArray(lexicalScope)) {
159157
for (let i = 0; i < lexicalScope.length; i++) {
160-
lexicalScope[i] = unwrapSubscriber(lexicalScope[i]);
161158
if (qDev) {
162159
verifySerializable(getProxyTarget(lexicalScope[i]) ?? lexicalScope[i]);
163160
}

packages/qwik/src/core/index.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ export { useServerMount$, useServerMountQrl } from './use/use-watch';
5050
export { useClientMount$, useClientMountQrl } from './use/use-watch';
5151
export { useMount$, useMountQrl } from './use/use-watch';
5252

53-
export { handleWatch } from './use/use-watch';
54-
5553
//////////////////////////////////////////////////////////////////////////////////////////
5654
// JSX Runtime
5755
//////////////////////////////////////////////////////////////////////////////////////////
@@ -61,17 +59,11 @@ export { Slot } from './render/jsx/slot.public';
6159
export { Fragment, jsx, jsxDEV, jsxs } from './render/jsx/jsx-runtime';
6260
export type { HTMLAttributes, AriaAttributes } from './render/jsx/types/jsx-generated';
6361
export type { DOMAttributes } from './render/jsx/types/jsx-qwik-attributes';
64-
export type {
65-
ComponentChild,
66-
ComponentChildren,
67-
FunctionComponent,
68-
JSXFactory,
69-
JSXNode,
70-
RenderableProps,
71-
} from './render/jsx/types/jsx-node';
62+
export type { FunctionComponent, JSXNode } from './render/jsx/types/jsx-node';
7263
export type { QwikDOMAttributes, QwikJSX } from './render/jsx/types/jsx-qwik';
7364
export type { QwikIntrinsicElements } from './render/jsx/types/jsx-qwik-elements';
7465
export { render } from './render/render.public';
66+
export { handleWatch } from './render/notify-render';
7567

7668
//////////////////////////////////////////////////////////////////////////////////////////
7769
// use API
@@ -80,7 +72,6 @@ export { useHostElement } from './use/use-host-element.public';
8072
export { useDocument } from './use/use-document.public';
8173
export { useLexicalScope } from './use/use-lexical-scope.public';
8274
export { useStore, useRef, useSequentialScope } from './use/use-store.public';
83-
export { wrapSubscriber, unwrapSubscriber } from './use/use-subscriber';
8475
export { useContext, useContextProvider, createContext } from './use/use-context';
8576
export { useWaitOn } from './use/use-core';
8677
export { useStylesQrl, useStyles$, useScopedStylesQrl, useScopedStyles$ } from './use/use-styles';

0 commit comments

Comments
 (0)