diff --git a/.gitignore b/.gitignore
index f9e25c5..6c8a02d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -193,3 +193,5 @@ dist
# End of https://www.toptal.com/developers/gitignore/api/node,linux,macos
dist
+
+.idea
diff --git a/package.json b/package.json
index 8bf2345..9de8241 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"node": ">=18.6.0"
},
"dependencies": {
+ "@effector/next": "^0.7.0",
"@effector/reflect": "^9.2.0",
"@fastify/accepts": "^4.3.0",
"@fastify/compress": "^7.0.3",
diff --git a/pages/+Wrapper.tsx b/pages/+Wrapper.tsx
index 412c21f..8c4c672 100644
--- a/pages/+Wrapper.tsx
+++ b/pages/+Wrapper.tsx
@@ -1,11 +1,36 @@
import type React from "react";
+import { useEffect, useRef } from "react";
-import { fork } from "effector";
-import { Provider } from "effector-react";
+import { EffectorNext } from "@effector/next";
+import { createEvent } from "effector";
+import { useUnit } from "effector-react";
import { usePageContext } from "vike-react/usePageContext";
+const noop = createEvent();
+
+const Inner = () => {
+ const { config } = usePageContext();
+ const clientStartedRef = useRef(false);
+ const onClientStarted = useUnit(config.pageClientStarted ?? noop);
+
+ useEffect(() => {
+ if (!clientStartedRef.current && "pageClientStarted" in config) {
+ onClientStarted();
+ clientStartedRef.current = true;
+ }
+ }, []);
+
+ return <>>;
+};
+
export default function WrapperEffector({ children }: { children: React.ReactNode }) {
- const { scopeValues } = usePageContext();
+ const pageContext = usePageContext();
+ const { scopeValues } = pageContext;
- return {children};
+ return (
+
+
+ {children}
+
+ );
}
diff --git a/pages/example/@id/+Page.tsx b/pages/example/@id/+Page.tsx
index dbe0919..e7edbd6 100644
--- a/pages/example/@id/+Page.tsx
+++ b/pages/example/@id/+Page.tsx
@@ -1,15 +1,22 @@
import { useUnit } from "effector-react";
import { Link } from "~/shared/routing";
-import { $id } from "./model";
+import { $random } from "../../index/model";
+import { $clientId, $id } from "./model";
export function Page() {
const id = useUnit($id);
+ const clientId = useUnit($clientId);
+ const random = useUnit($random);
return (
Example
Read parameter from route: {id}
+
+ Client id: {clientId}
+ random: {random}
+
Go home
);
diff --git a/pages/example/@id/+pageClientStarted.ts b/pages/example/@id/+pageClientStarted.ts
new file mode 100644
index 0000000..a1c27cc
--- /dev/null
+++ b/pages/example/@id/+pageClientStarted.ts
@@ -0,0 +1,3 @@
+import { createEvent } from "effector";
+
+export const pageClientStarted = createEvent();
diff --git a/pages/example/@id/model.ts b/pages/example/@id/model.ts
index ab6ce07..29f4904 100644
--- a/pages/example/@id/model.ts
+++ b/pages/example/@id/model.ts
@@ -1,9 +1,11 @@
import { createStore, sample } from "effector";
import { redirectTo } from "~/shared/routing";
+import { pageClientStarted } from "./+pageClientStarted";
import { pageStarted } from "./+pageStarted";
export const $id = createStore("");
+export const $clientId = createStore(0);
const dataInitialized = sample({
clock: pageStarted,
@@ -21,3 +23,9 @@ sample({
fn: ({ sampleData: { id } }) => id,
target: $id,
});
+
+sample({
+ clock: pageClientStarted,
+ fn: () => 1,
+ target: $clientId,
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 760f7dd..e8ddd3b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
+ '@effector/next':
+ specifier: ^0.7.0
+ version: 0.7.0(effector-react@23.2.1(effector@23.2.2)(react@18.3.1))(effector@23.2.2)(react@18.3.1)
'@effector/reflect':
specifier: ^9.2.0
version: 9.2.0(effector-react@23.2.1(effector@23.2.2)(react@18.3.1))(effector@23.2.2)(react@18.3.1)
@@ -267,6 +270,13 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
+ '@effector/next@0.7.0':
+ resolution: {integrity: sha512-8KrtdGr/mYboIM5rq5r39j2gX9lXWu/AC/+Iyp882Y0G2WO6cr8opamdOlZaVaNdJYBJQ6IyuBslhmoI2TBAOw==}
+ peerDependencies:
+ effector: ^22.8.6 || ^23.0.0
+ effector-react: ^22.5.4 || ^23.0.0
+ react: ^18.2.0
+
'@effector/reflect@9.2.0':
resolution: {integrity: sha512-jumgC1Ztl28gRmhLei2TX3bF0p1sD/LhAWHWggbmiNcZnpX4K6odTITrFLSu4wKkyP+AX9QpF/wiqLi0njDP1A==}
peerDependencies:
@@ -2088,6 +2098,12 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
+ '@effector/next@0.7.0(effector-react@23.2.1(effector@23.2.2)(react@18.3.1))(effector@23.2.2)(react@18.3.1)':
+ dependencies:
+ effector: 23.2.2
+ effector-react: 23.2.1(effector@23.2.2)(react@18.3.1)
+ react: 18.3.1
+
'@effector/reflect@9.2.0(effector-react@23.2.1(effector@23.2.2)(react@18.3.1))(effector@23.2.2)(react@18.3.1)':
dependencies:
effector: 23.2.2
diff --git a/renderer/+config.ts b/renderer/+config.ts
index 2d0766a..f886cd8 100644
--- a/renderer/+config.ts
+++ b/renderer/+config.ts
@@ -14,9 +14,8 @@ export default {
pageStarted: {
env: { client: true, server: true },
},
- // https://effector.dev/en/api/effector/scope/
- scope: {
- env: { client: true, server: true },
+ pageClientStarted: {
+ env: { client: true, server: false },
},
},
diff --git a/renderer/+onBeforeRender.ts b/renderer/+onBeforeRender.ts
index 47dd5c4..8ba8a5a 100644
--- a/renderer/+onBeforeRender.ts
+++ b/renderer/+onBeforeRender.ts
@@ -28,7 +28,6 @@ export const onBeforeRender: OnBeforeRenderAsync = async (pageContext) => {
return {
pageContext: {
- scope,
// https://effector.dev/en/api/effector/serialize
scopeValues: serialize(scope),
},
diff --git a/renderer/+onBeforeRenderClient.ts b/renderer/+onBeforeRenderClient.ts
index 292bcd7..7c30afc 100644
--- a/renderer/+onBeforeRenderClient.ts
+++ b/renderer/+onBeforeRenderClient.ts
@@ -1,14 +1,15 @@
-import { fork } from "effector";
+import { allSettled, fork, serialize } from "effector";
// https://vike.dev/onBeforeRenderClient
-export function onBeforeRenderClient(pageContext: Vike.PageContext) {
+export async function onBeforeRenderClient(pageContext: Vike.PageContext) {
// https://vike.dev/pageContext
- if (!("scope" in pageContext)) {
- return {
- pageContext: {
- // https://effector.dev/en/api/effector/fork/
- scope: fork({ values: pageContext.scopeValues }),
- },
- };
+
+ const scope = fork({ values: pageContext.scopeValues });
+
+ const pageClientStarted = pageContext.config.pageClientStarted;
+
+ if (pageClientStarted && !pageContext.isHydration) {
+ await allSettled(pageClientStarted, { scope });
+ pageContext.scopeValues = serialize(scope);
}
}
diff --git a/renderer/types.ts b/renderer/types.ts
index b3a7bd9..22f7919 100644
--- a/renderer/types.ts
+++ b/renderer/types.ts
@@ -1,4 +1,4 @@
-import type { EventCallable, Scope } from "effector";
+import type { EventCallable } from "effector";
// https://vike.dev/pageContext#typescript
declare global {
@@ -6,10 +6,8 @@ declare global {
interface PageContext {
config: {
pageStarted?: EventCallable<{ params: Record; data: unknown }>;
+ pageClientStarted?: EventCallable;
};
-
- // https://effector.dev/en/api/effector/scope/
- scope?: Scope;
scopeValues?: Record;
}
}