diff --git a/packages/preact/src/entry-server.tsx b/packages/preact/src/entry-server.tsx
index 5eee836..a6fee56 100644
--- a/packages/preact/src/entry-server.tsx
+++ b/packages/preact/src/entry-server.tsx
@@ -1,12 +1,10 @@
-import { useContext } from "preact/hooks";
import renderToString from "preact-render-to-string";
import type { ComponentType } from "preact";
import type { Context, RouteModule } from "@impalajs/core";
-import { HeadContext } from "./head-context";
+import { HeadContext, HeadManager } from "./head-context";
-function HeadContent() {
- const headProvider = useContext(HeadContext);
- return <>{...headProvider.getHead()}>;
+function HeadContent({ headManager }: { headManager: HeadManager }) {
+ return <>{...headManager.getHead()}>;
}
export async function render(
@@ -16,13 +14,22 @@ export async function render(
) {
const { default: Page } = await mod();
- const body = renderToString();
+ // We create a new head manager for each request to avoid sharing state across routes
+ const headManager = new HeadManager();
+
+ // Now on each render, each page will use their own head context instead of default one
+ const body = renderToString(
+
+
+
+ );
const modules = bootstrapModules?.map(
(m) => ``
);
- const headContent = renderToString();
+ // We then pass the head manager instance that is specific to this request to SSR
+ const headContent = renderToString();
return {
body,
diff --git a/packages/preact/src/head-context.tsx b/packages/preact/src/head-context.tsx
index c82f6a6..2691f5b 100644
--- a/packages/preact/src/head-context.tsx
+++ b/packages/preact/src/head-context.tsx
@@ -1,6 +1,6 @@
import { createContext, VNode } from "preact";
-class HeadProvider {
+export class HeadManager {
private head: VNode[] = [];
private removeTag(tag: string) {
@@ -31,6 +31,6 @@ class HeadProvider {
}
}
-const headProvider = new HeadProvider();
+const defaultHeadProvider = new HeadManager();
-export const HeadContext = createContext(headProvider);
+export const HeadContext = createContext(defaultHeadProvider);
diff --git a/packages/react/src/entry-server.tsx b/packages/react/src/entry-server.tsx
index 6280a5a..224d318 100644
--- a/packages/react/src/entry-server.tsx
+++ b/packages/react/src/entry-server.tsx
@@ -1,8 +1,8 @@
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
-import { ElementType, useContext } from "react";
+import { ElementType } from "react";
import type { Context, RouteModule } from "@impalajs/core";
import { Writable, WritableOptions } from "node:stream";
-import { HeadContext } from "./head-context";
+import { HeadContext, HeadManager } from "./head-context";
class StringResponse extends Writable {
private buffer: string;
@@ -30,9 +30,8 @@ class StringResponse extends Writable {
}
}
-function HeadContent() {
- const headProvider = useContext(HeadContext);
- return <>{...headProvider.getHead()}>;
+function HeadContent({ headManager }: { headManager: HeadManager }) {
+ return <>{...headManager.getHead()}>;
}
export async function render(
@@ -42,22 +41,32 @@ export async function render(
) {
const { default: Page } = await mod();
+ // We create a new head manager for each request to avoid sharing state across routes
+ const headManager = new HeadManager();
+
const response = new StringResponse();
- const { pipe } = renderToPipeableStream(, {
- bootstrapModules,
- bootstrapScriptContent: `window.___CONTEXT=${JSON.stringify(context)};`,
- onAllReady() {
- pipe(response);
- },
- onError(error) {
- console.error(error);
- },
- });
+ const { pipe } = renderToPipeableStream(
+ // Now on each render, each page will use their own head context instead of default one
+ (
+
+
+
+ ),
+ {
+ bootstrapModules,
+ bootstrapScriptContent: `window.___CONTEXT=${JSON.stringify(context)};`,
+ onAllReady() {
+ pipe(response);
+ },
+ onError(error) {
+ console.error(error);
+ },
+ });
const body = await response.getData();
- const head = renderToStaticMarkup();
+ const head = renderToStaticMarkup();
return { body, head };
}
diff --git a/packages/react/src/head-context.tsx b/packages/react/src/head-context.tsx
index b65d899..8ce7fa5 100644
--- a/packages/react/src/head-context.tsx
+++ b/packages/react/src/head-context.tsx
@@ -1,6 +1,6 @@
import React, { createContext, ReactElement, ReactNode } from "react";
-class HeadProvider {
+export class HeadManager {
private head: React.ReactElement[] = [];
private removeTag(tag: string) {
@@ -31,6 +31,6 @@ class HeadProvider {
}
}
-const headProvider = new HeadProvider();
+const defaultHeadManager = new HeadManager();
-export const HeadContext = createContext(headProvider);
+export const HeadContext = createContext(defaultHeadManager);