Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "qwik-monorepo",
"version": "0.0.20-8",
"version": "0.0.20",
"scripts": {
"build": "yarn node scripts --tsc --build --api --platform-binding-wasm-copy",
"build.full": "yarn node scripts --tsc --build --api --eslint --platform-binding --wasm",
Expand Down
2 changes: 1 addition & 1 deletion packages/create-qwik/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-qwik",
"version": "0.0.20-8",
"version": "0.0.20",
"description": "Interactive CLI and API for generating Qwik projects.",
"bin": "create-qwik",
"main": "index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const requestHandler = (ev: FetchEvent) => {
headers: {
'Content-Type': 'application/javascript; charset=utf-8',
'Cache-Control': 'no-store',
'X-Qwik-REPL-App': 'client-module',
'X-Qwik-REPL-App': 'ssr-result',
'X-Qwik-Client-Id': clientId,
},
})
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-qwik/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-qwik",
"version": "0.0.20-8",
"version": "0.0.20",
"description": "An Open-Source sub-framework designed with a focus on server-side-rendering, lazy-loading, and styling/animation.",
"main": "index.js",
"author": "Builder Team",
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@builder.io/qwik",
"version": "0.0.20-8",
"version": "0.0.20",
"description": "An Open-Source sub-framework designed with a focus on server-side-rendering, lazy-loading, and styling/animation.",
"main": "./dist/core.cjs",
"module": "./dist/core.mjs",
Expand Down
24 changes: 22 additions & 2 deletions packages/qwik/src/core/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ export type On$Props<T extends {}> = {
};

// @public (undocumented)
export type OnRenderFn<PROPS> = (props: PROPS) => ValueOrPromise<JSXNode<any> | null>;
export type OnRenderFn<PROPS> = (props: PROPS) => ValueOrPromise<JSXNode<any> | null | (() => JSXNode<any>)>;

// @alpha
export function pauseContainer(elmOrDoc: Element | Document): SnapshotResult;
Expand Down Expand Up @@ -576,6 +576,16 @@ export const useClientEffect$: (first: WatchFn, opts?: UseEffectOptions | undefi
// @public
export function useClientEffectQrl(qrl: QRL<WatchFn>, opts?: UseEffectOptions): void;

// Warning: (ae-incompatible-release-tags) The symbol "useClientMount$" is marked as @public, but its signature references "ServerFn" which is marked as @alpha
//
// @public
export const useClientMount$: (first: ServerFn) => void;

// Warning: (ae-incompatible-release-tags) The symbol "useClientMountQrl" is marked as @public, but its signature references "ServerFn" which is marked as @alpha
//
// @public
export function useClientMountQrl(mountQrl: QRL<ServerFn>): void;

// @alpha (undocumented)
export function useContext<STATE extends object>(context: Context<STATE>): STATE;

Expand All @@ -600,6 +610,16 @@ export function useHostElement(): Element;
// @public
export function useLexicalScope<VARS extends any[]>(): VARS;

// Warning: (ae-incompatible-release-tags) The symbol "useMount$" is marked as @public, but its signature references "ServerFn" which is marked as @alpha
//
// @public
export const useMount$: (first: ServerFn) => void;

// Warning: (ae-incompatible-release-tags) The symbol "useMountQrl" is marked as @public, but its signature references "ServerFn" which is marked as @alpha
//
// @public
export function useMountQrl(mountQrl: QRL<ServerFn>): void;

// @alpha
export function useOn(event: string, eventFn: QRL<() => void>): void;

Expand Down Expand Up @@ -634,7 +654,7 @@ export const useServerMount$: (first: ServerFn) => void;
// Warning: (ae-incompatible-release-tags) The symbol "useServerMountQrl" is marked as @public, but its signature references "ServerFn" which is marked as @alpha
//
// @public
export function useServerMountQrl(watchQrl: QRL<ServerFn>): void;
export function useServerMountQrl(mountQrl: QRL<ServerFn>): void;

// @public
export function useStore<STATE extends object>(initialState: STATE | (() => STATE)): STATE;
Expand Down
6 changes: 5 additions & 1 deletion packages/qwik/src/core/component/component-ctx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,14 @@ export const renderComponent = (rctx: RenderContext, ctx: QContext): ValueOrProm
appendStyle(rctx, hostElement, task);
}
});
if (ctx.dirty) {
if (typeof jsxNode === 'function') {
ctx.dirty = false;
jsxNode = jsxNode();
} else if (ctx.dirty) {
logDebug('Dropping render. State changed during render.');
return renderComponent(rctx, ctx);
}

let componentCtx = ctx.component;
if (!componentCtx) {
componentCtx = ctx.component = {
Expand Down
4 changes: 3 additions & 1 deletion packages/qwik/src/core/component/component.public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,9 @@ export function component$<PROPS extends {}>(
/**
* @public
*/
export type OnRenderFn<PROPS> = (props: PROPS) => ValueOrPromise<JSXNode<any> | null>;
export type OnRenderFn<PROPS> = (
props: PROPS
) => ValueOrPromise<JSXNode<any> | null | (() => JSXNode<any>)>;

export interface RenderFactoryOutput<PROPS> {
renderQRL: QRL<OnRenderFn<PROPS>>;
Expand Down
54 changes: 36 additions & 18 deletions packages/qwik/src/core/examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ import {
} from './component/component.public';
import { Host } from './render/jsx/host.public';
import { $, implicit$FirstArg, QRL } from './import/qrl.public';
import { useClientEffect$, useServerMount$, useWatch$ } from './watch/watch.public';
import {
useClientEffect$,
useServerMount$,
useClientMount$,
useMount$,
useWatch$,
} from './watch/watch.public';
import { useHostElement } from './use/use-host-element.public';
import { useRef } from './use/use-store.public';

Expand Down Expand Up @@ -249,7 +255,6 @@ export const CmpInline = component$(() => {
users: [],
});

// Double count watch
useServerMount$(async () => {
// This code will ONLY run once in the server, when the component is mounted
store.users = await db.requestUsers();
Expand All @@ -275,34 +280,47 @@ export const CmpInline = component$(() => {
};

() => {
let db: any;
// <docs anchor="use-server-mount">
// <docs anchor="use-client-mount">
const Cmp = component$(() => {
const store = useStore({
users: [],
hash: '',
});

// Double count watch
useServerMount$(async () => {
// This code will ONLY run once in the server, when the component is mounted
store.users = await db.requestUsers();
useClientMount$(async () => {
// This code will ONLY run once in the client, when the component is mounted
store.hash = document.location.hash;
});

return (
<Host>
{store.users.map((user) => (
<User user={user} />
))}
<p>The url hash is: ${store.hash}</p>
</Host>
);
});
// </docs>
return Cmp;
};

interface User {
name: string;
}
function User(props: { user: User }) {
return <div>Name: {props.user.name}</div>;
}
() => {
// <docs anchor="use-mount">
const Cmp = component$(() => {
const store = useStore({
temp: 0,
});

useMount$(async () => {
// This code will run once whenever a component is mounted in the server, or in the client
const res = await fetch('weather-api.example');
const json = (await res.json()) as any;
store.temp = json.temp;
});

return (
<Host>
<p>The temperature is: ${store.temp}</p>
</Host>
);
});
// </docs>
return Cmp;
};
Expand Down
8 changes: 3 additions & 5 deletions packages/qwik/src/core/import/qrl-class.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { InvokeContext, newInvokeContext, useInvoke } from '../use/use-core';
import { emitEvent } from '../util/event';
import { then } from '../util/promises';
import type { ValueOrPromise } from '../util/types';
import { qrlImport, QRLSerializeOptions, stringifyQRL } from './qrl';
Expand Down Expand Up @@ -90,11 +89,10 @@ export const getCanonicalSymbol = (symbolName: string) => {
};

export const isSameQRL = (a: QRL<any>, b: QRL<any>): boolean => {
return getCanonicalSymbol(a.symbol) === getCanonicalSymbol(b.symbol);
const symA = a.refSymbol ?? a.symbol;
const symB = b.refSymbol ?? b.symbol;
return getCanonicalSymbol(symA) === getCanonicalSymbol(symB);
};

export type QRLInternal<T = any> = QRL<T>;
export const QRLInternal: typeof QRL = QRL;

// https://regexr.com/6enjv
const FIND_EXT = /\?[\w=&]+$/;
3 changes: 3 additions & 0 deletions packages/qwik/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export type {
export { useWatch$, useWatchQrl } from './watch/watch.public';
export { useClientEffect$, useClientEffectQrl } from './watch/watch.public';
export { useServerMount$, useServerMountQrl } from './watch/watch.public';
export { useClientMount$, useClientMountQrl } from './watch/watch.public';
export { useMount$, useMountQrl } from './watch/watch.public';

export { handleWatch } from './watch/watch.public';

//////////////////////////////////////////////////////////////////////////////////////////
Expand Down
34 changes: 29 additions & 5 deletions packages/qwik/src/core/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,44 @@ The `obs` passed into the `watchFn` is used to mark `state.count` as a property

@public

# `useServerMount`
# `useClientEffect`

<docs code="./examples.tsx#use-client-effect"/>

@public

Register's a server mount hook, that runs only in server when the component is first mounted. `useWatch` will run once in the server, and N-times in the client, only when the **tracked** state changes.
# `useMount`

Register's a mount hook, that runs both in the server and the client when the component is first mounted.

## Example

<docs code="./examples.tsx#use-server-mount"/>
<docs code="./examples.tsx#use-mount"/>

@see `useServerMount` `useClientMount`
@public

# `useClientEffect`
# `useClientMount`

<docs code="./examples.tsx#use-client-effect"/>
Register's a client mount hook, that runs only in client when the component is first mounted.

## Example

<docs code="./examples.tsx#use-client-mount"/>

@see `useServerMount` `useMount`

@public

# `useServerMount`

Register's a server mount hook, that runs only in server when the component is first mounted.

## Example

<docs code="./examples.tsx#use-server-mount"/>

@see `useClientMount` `useMount`
@public

# `useStyles`
Expand Down
Loading