vike-react 0.6.17 → 0.6.19

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.
@@ -1,11 +1,14 @@
1
1
  export { ClientOnly };
2
- import React, { useEffect } from 'react';
2
+ import React from 'react';
3
3
  import type { ReactNode } from 'react';
4
- declare function ClientOnly<T>({ load, children, fallback, deps, }: {
5
- load: () => Promise<{
6
- default: React.ComponentType<T>;
7
- } | React.ComponentType<T>>;
8
- children: (Component: React.ComponentType<T>) => ReactNode;
9
- fallback: ReactNode;
10
- deps?: Parameters<typeof useEffect>[1];
11
- }): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
4
+ /**
5
+ * Render children only on the client-side.
6
+ *
7
+ * Children are completely removed and never loaded on the server.
8
+ *
9
+ * https://vike.dev/ClientOnly
10
+ */
11
+ declare function ClientOnly({ children, fallback }: {
12
+ children: ReactNode;
13
+ fallback?: ReactNode;
14
+ }): React.JSX.Element;
@@ -1,26 +1,20 @@
1
1
  export { ClientOnly };
2
- import React, { lazy, useEffect, useState, startTransition } from 'react';
3
- function ClientOnly({ load, children, fallback, deps = [], }) {
4
- // TO-DO/next-major: remove this file/export
5
- console.warn('[vike-react][warning] <ClientOnly> is deprecated: use clientOnly() instead https://vike.dev/clientOnly');
6
- const [Component, setComponent] = useState(null);
7
- useEffect(() => {
8
- const loadComponent = () => {
9
- const Component = lazy(() => load()
10
- .then((LoadedComponent) => {
11
- return {
12
- default: () => children('default' in LoadedComponent ? LoadedComponent.default : LoadedComponent),
13
- };
14
- })
15
- .catch((error) => {
16
- console.error('Component loading failed:', error);
17
- return { default: () => React.createElement("p", null, "Error loading component.") };
18
- }));
19
- setComponent(Component);
20
- };
21
- startTransition(() => {
22
- loadComponent();
23
- });
24
- }, deps);
25
- return Component ? React.createElement(Component, null) : fallback;
2
+ import React from 'react';
3
+ import { usePageContext } from '../hooks/usePageContext.js';
4
+ import { useHydrated } from '../hooks/useHydrated.js';
5
+ import { assert } from '../utils/assert.js';
6
+ /**
7
+ * Render children only on the client-side.
8
+ *
9
+ * Children are completely removed and never loaded on the server.
10
+ *
11
+ * https://vike.dev/ClientOnly
12
+ */
13
+ function ClientOnly({ children, fallback }) {
14
+ const pageContext = usePageContext();
15
+ // Assert tree-shaking: children should be statically removed on the server-side
16
+ if (!pageContext.isClientSide)
17
+ assert(children === undefined);
18
+ const hydrated = useHydrated();
19
+ return React.createElement(React.Fragment, null, hydrated ? children : fallback);
26
20
  }
package/dist/config.d.ts CHANGED
@@ -11,6 +11,51 @@ declare const config: {
11
11
  passToClient: string[];
12
12
  clientRouting: true;
13
13
  hydrationCanBeAborted: true;
14
+ staticReplace: ({
15
+ env: "server";
16
+ filter: string;
17
+ type: "call";
18
+ match: {
19
+ function: string[];
20
+ args: {
21
+ 0: string;
22
+ };
23
+ };
24
+ remove: {
25
+ arg: number;
26
+ prop: string;
27
+ argsFrom?: undefined;
28
+ };
29
+ replace?: undefined;
30
+ } | {
31
+ env: "server";
32
+ filter: string;
33
+ type: "call";
34
+ match: {
35
+ function: string;
36
+ args: {
37
+ 0: string;
38
+ };
39
+ };
40
+ remove: {
41
+ argsFrom: number;
42
+ arg?: undefined;
43
+ prop?: undefined;
44
+ };
45
+ replace?: undefined;
46
+ } | {
47
+ env: "server";
48
+ filter: string;
49
+ type: "call";
50
+ match: {
51
+ function: string;
52
+ args?: undefined;
53
+ };
54
+ replace: {
55
+ with: boolean;
56
+ };
57
+ remove?: undefined;
58
+ })[];
14
59
  meta: {
15
60
  Head: {
16
61
  env: {
package/dist/config.js CHANGED
@@ -5,7 +5,7 @@ const config = {
5
5
  // @eject-remove start
6
6
  name: 'vike-react',
7
7
  require: {
8
- vike: '>=0.4.242',
8
+ vike: '>=0.4.250',
9
9
  },
10
10
  Loading: 'import:vike-react/__internal/integration/Loading:default',
11
11
  // https://vike.dev/onRenderHtml
@@ -21,6 +21,42 @@ const config = {
21
21
  // https://vike.dev/clientRouting
22
22
  clientRouting: true,
23
23
  hydrationCanBeAborted: true,
24
+ // Remove <ClientOnly> children on server
25
+ staticReplace: [
26
+ {
27
+ env: 'server',
28
+ filter: 'vike-react/ClientOnly',
29
+ type: 'call',
30
+ match: {
31
+ function: [
32
+ 'import:react/jsx-runtime:jsx',
33
+ 'import:react/jsx-runtime:jsxs',
34
+ 'import:react/jsx-dev-runtime:jsxDEV',
35
+ ],
36
+ args: { 0: 'import:vike-react/ClientOnly:ClientOnly' },
37
+ },
38
+ remove: { arg: 1, prop: 'children' },
39
+ },
40
+ {
41
+ env: 'server',
42
+ filter: 'vike-react/ClientOnly',
43
+ type: 'call',
44
+ match: {
45
+ function: 'import:react:createElement',
46
+ args: { 0: 'import:vike-react/ClientOnly:ClientOnly' },
47
+ },
48
+ remove: { argsFrom: 2 },
49
+ },
50
+ {
51
+ env: 'server',
52
+ filter: 'vike-react/useHydrated',
53
+ type: 'call',
54
+ match: {
55
+ function: 'import:vike-react/useHydrated:useHydrated',
56
+ },
57
+ replace: { with: false },
58
+ },
59
+ ],
24
60
  // https://vike.dev/meta
25
61
  meta: {
26
62
  Head: {
@@ -1,11 +1,14 @@
1
+ // TO-DO/breaking-change: remove it
1
2
  export { clientOnly };
2
3
  import React, { Suspense, forwardRef, lazy, useEffect, useState, } from 'react';
4
+ import { assertWarning } from '../utils/assert.js';
3
5
  /**
4
6
  * Load and render a component only on the client-side.
5
7
  *
6
8
  * https://vike.dev/clientOnly
7
9
  */
8
10
  function clientOnly(load) {
11
+ assertWarning(false, 'clientOnly() is deprecated — use <ClientOnly> https://vike.dev/ClientOnly');
9
12
  if (!globalThis.__VIKE__IS_CLIENT) {
10
13
  return (props) => React.createElement(React.Fragment, null, props.fallback);
11
14
  }
@@ -0,0 +1,19 @@
1
+ export { useHydrated };
2
+ /**
3
+ * Whether the page has already been hydrated.
4
+ *
5
+ * On the server, it always returns `false`. On the client, it returns `false` on first render and `true` after hydration completes.
6
+ *
7
+ * https://vike.dev/useHydrated
8
+ *
9
+ * Example: Disable a button that needs JavaScript to work.
10
+ * ```tsx
11
+ * const hydrated = useHydrated()
12
+ * return (
13
+ * <button type="button" disabled={!hydrated} onClick={doSomething}>
14
+ * Click me
15
+ * </button>
16
+ * );
17
+ * ```
18
+ */
19
+ declare function useHydrated(): boolean;
@@ -0,0 +1,26 @@
1
+ export { useHydrated };
2
+ import { useSyncExternalStore } from 'react';
3
+ // Copied from https://github.com/sergiodxa/remix-utils/blob/33e6b04a08ef5f9b65e89c0a280c12b83762ef66/src/react/use-hydrated.ts
4
+ /**
5
+ * Whether the page has already been hydrated.
6
+ *
7
+ * On the server, it always returns `false`. On the client, it returns `false` on first render and `true` after hydration completes.
8
+ *
9
+ * https://vike.dev/useHydrated
10
+ *
11
+ * Example: Disable a button that needs JavaScript to work.
12
+ * ```tsx
13
+ * const hydrated = useHydrated()
14
+ * return (
15
+ * <button type="button" disabled={!hydrated} onClick={doSomething}>
16
+ * Click me
17
+ * </button>
18
+ * );
19
+ * ```
20
+ */
21
+ function useHydrated() {
22
+ return useSyncExternalStore(subscribeDummy, () => true, () => false);
23
+ }
24
+ function subscribeDummy() {
25
+ return () => { };
26
+ }
@@ -1 +1,4 @@
1
- export declare function assert(condition: unknown): asserts condition;
1
+ export { assert };
2
+ export { assertWarning };
3
+ declare function assert(condition: unknown): asserts condition;
4
+ declare function assertWarning(condition: unknown, message: string): void;
@@ -1,5 +1,12 @@
1
- export function assert(condition) {
1
+ export { assert };
2
+ export { assertWarning };
3
+ function assert(condition) {
2
4
  if (condition)
3
5
  return;
4
6
  throw new Error('You stumbled upon a vike-react bug, reach out on GitHub.');
5
7
  }
8
+ function assertWarning(condition, message) {
9
+ if (condition)
10
+ return;
11
+ console.warn(new Error(message));
12
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "vike-react",
3
- "version": "0.6.17",
3
+ "version": "0.6.19",
4
4
  "repository": "https://github.com/vikejs/vike-react",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./usePageContext": "./dist/hooks/usePageContext.js",
8
8
  "./useData": "./dist/hooks/useData.js",
9
+ "./useHydrated": "./dist/hooks/useHydrated.js",
9
10
  "./useConfig": {
10
11
  "browser": "./dist/hooks/useConfig/useConfig-client.js",
11
12
  "default": "./dist/hooks/useConfig/useConfig-server.js"
@@ -32,7 +33,7 @@
32
33
  "peerDependencies": {
33
34
  "react": ">=19",
34
35
  "react-dom": ">=19",
35
- "vike": ">=0.4.242"
36
+ "vike": ">=0.4.250"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@biomejs/biome": "^1.9.4",
@@ -44,7 +45,7 @@
44
45
  "react-dom": "^19.2.1",
45
46
  "rimraf": "^5.0.5",
46
47
  "typescript": "^5.9.2",
47
- "vike": "^0.4.249",
48
+ "vike": "^0.4.252",
48
49
  "vite": "^7.3.0"
49
50
  },
50
51
  "typesVersions": {
@@ -55,6 +56,9 @@
55
56
  "usePageContext": [
56
57
  "./dist/hooks/usePageContext.d.ts"
57
58
  ],
59
+ "useHydrated": [
60
+ "./dist/hooks/useHydrated.d.ts"
61
+ ],
58
62
  "useConfig": [
59
63
  "./dist/hooks/useConfig/useConfig-server.d.ts"
60
64
  ],