Skip to content

Commit d3741cd

Browse files
committed
fix(react)!: add <HeadProvider />
1 parent fc19149 commit d3741cd

File tree

3 files changed

+29
-19
lines changed

3 files changed

+29
-19
lines changed

packages/preact/src/entry-server.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export async function render(
1717
// We create a new head manager for each request to avoid sharing state across routes
1818
const headManager = new HeadManager();
1919

20+
// Now on each render, each page will use their own head context instead of default one
2021
const body = renderToString(
2122
<HeadContext.Provider value={headManager}>
2223
<Page {...context} />

packages/react/src/entry-server.tsx

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
2-
import { ElementType, useContext } from "react";
2+
import { ElementType } from "react";
33
import type { Context, RouteModule } from "@impalajs/core";
44
import { Writable, WritableOptions } from "node:stream";
5-
import { HeadContext } from "./head-context";
5+
import { HeadContext, HeadManager } from "./head-context";
66

77
class StringResponse extends Writable {
88
private buffer: string;
@@ -30,9 +30,8 @@ class StringResponse extends Writable {
3030
}
3131
}
3232

33-
function HeadContent() {
34-
const headProvider = useContext(HeadContext);
35-
return <>{...headProvider.getHead()}</>;
33+
function HeadContent({ headManager }: { headManager: HeadManager }) {
34+
return <>{...headManager.getHead()}</>;
3635
}
3736

3837
export async function render(
@@ -42,22 +41,32 @@ export async function render(
4241
) {
4342
const { default: Page } = await mod();
4443

44+
// We create a new head manager for each request to avoid sharing state across routes
45+
const headManager = new HeadManager();
46+
4547
const response = new StringResponse();
4648

47-
const { pipe } = renderToPipeableStream(<Page {...context} />, {
48-
bootstrapModules,
49-
bootstrapScriptContent: `window.___CONTEXT=${JSON.stringify(context)};`,
50-
onAllReady() {
51-
pipe(response);
52-
},
53-
onError(error) {
54-
console.error(error);
55-
},
56-
});
49+
const { pipe } = renderToPipeableStream(
50+
// Now on each render, each page will use their own head context instead of default one
51+
(
52+
<HeadContext.Provider value={headManager}>
53+
<Page {...context} />
54+
</HeadContext.Provider>
55+
),
56+
{
57+
bootstrapModules,
58+
bootstrapScriptContent: `window.___CONTEXT=${JSON.stringify(context)};`,
59+
onAllReady() {
60+
pipe(response);
61+
},
62+
onError(error) {
63+
console.error(error);
64+
},
65+
});
5766

5867
const body = await response.getData();
5968

60-
const head = renderToStaticMarkup(<HeadContent />);
69+
const head = renderToStaticMarkup(<HeadContent headManager={headManager} />);
6170

6271
return { body, head };
6372
}

packages/react/src/head-context.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { createContext, ReactElement, ReactNode } from "react";
22

3-
class HeadProvider {
3+
export class HeadManager {
44
private head: React.ReactElement[] = [];
55

66
private removeTag(tag: string) {
@@ -31,6 +31,6 @@ class HeadProvider {
3131
}
3232
}
3333

34-
const headProvider = new HeadProvider();
34+
const defaultHeadManager = new HeadManager();
3535

36-
export const HeadContext = createContext(headProvider);
36+
export const HeadContext = createContext(defaultHeadManager);

0 commit comments

Comments
 (0)