Skip to content

Commit a5ebbe7

Browse files
committed
Use global variable with uniqueRenderId
1 parent e3ac705 commit a5ebbe7

13 files changed

+211
-31
lines changed

packages/render/src/browser/render-async-web.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @vitest-environment jsdom
33
*/
44

5+
import { randomUUID } from 'crypto';
56
import { Preview } from '../shared/utils/preview';
67
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
78
import { renderAsync } from './render-async';
@@ -129,10 +130,39 @@ describe('renderAsync on the browser environment', () => {
129130
expect(actualOutput).toMatchInlineSnapshot(`
130131
"HELLO, JIM!
131132
132-
Thanks for trying our product."
133+
Thanks for trying our plaintext product."
133134
`);
134135
});
135136

137+
it('successfully passes rendering options when using uniqueRenderId', async () => {
138+
const uniqueRenderId = randomUUID();
139+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
140+
plainText: true,
141+
uniqueRenderId: uniqueRenderId
142+
});
143+
144+
expect(actualOutput).toMatchInlineSnapshot(`
145+
"HELLO, JIM!
146+
147+
Thanks for trying our plaintext product."
148+
`);
149+
});
150+
151+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
152+
const uniqueRenderId1 = randomUUID();
153+
const uniqueRenderId2 = randomUUID();
154+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
155+
plainText: true,
156+
uniqueRenderId: uniqueRenderId2
157+
});
158+
159+
expect(actualOutput).toMatchInlineSnapshot(`
160+
"WELCOME, JIM!
161+
162+
Thanks for trying our product. We're thrilled to have you on board!"
163+
`);
164+
});
165+
136166
it('converts to plain text and removes reserved ID', async () => {
137167
const actualOutput = await renderAsync(<Preview />, {
138168
plainText: true,

packages/render/src/browser/render-async.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import type { Options } from '../shared/options';
44
import { plainTextSelectors } from '../shared/plain-text-selectors';
55
import { pretty } from '../shared/utils/pretty';
66
import { readStream } from './read-stream';
7-
import { OptionsContext } from '../shared/useRenderingOptions';
7+
import { setRenderingOptions } from '../shared/useRenderingOptions';
88

99
export const renderAsync = async (
1010
element: React.ReactElement,
1111
options?: Options,
1212
) => {
13-
const suspendedElement = <Suspense>
14-
<OptionsContext.Provider value={options ?? {}}>{element}</OptionsContext.Provider>
15-
</Suspense>;
13+
setRenderingOptions(options?.uniqueRenderId, options)
14+
const suspendedElement = <Suspense>{element}</Suspense>;
1615
const reactDOMServer = await import('react-dom/server');
1716

1817
let html!: string;

packages/render/src/browser/render-web.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @vitest-environment jsdom
33
*/
44

5+
import { randomUUID } from 'crypto';
56
import { Preview } from '../shared/utils/preview';
67
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
78
import { render } from './render';
@@ -129,10 +130,39 @@ describe('render on the browser environment', () => {
129130
expect(actualOutput).toMatchInlineSnapshot(`
130131
"HELLO, JIM!
131132
132-
Thanks for trying our product."
133+
Thanks for trying our plaintext product."
133134
`);
134135
});
135136

137+
it('successfully passes rendering options when using uniqueRenderId', async () => {
138+
const uniqueRenderId = randomUUID();
139+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
140+
plainText: true,
141+
uniqueRenderId: uniqueRenderId
142+
});
143+
144+
expect(actualOutput).toMatchInlineSnapshot(`
145+
"HELLO, JIM!
146+
147+
Thanks for trying our plaintext product."
148+
`);
149+
});
150+
151+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
152+
const uniqueRenderId1 = randomUUID();
153+
const uniqueRenderId2 = randomUUID();
154+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
155+
plainText: true,
156+
uniqueRenderId: uniqueRenderId2
157+
});
158+
159+
expect(actualOutput).toMatchInlineSnapshot(`
160+
"WELCOME, JIM!
161+
162+
Thanks for trying our product. We're thrilled to have you on board!"
163+
`);
164+
});
165+
136166
it('converts to plain text and removes reserved ID', async () => {
137167
const actualOutput = await render(<Preview />, {
138168
plainText: true,

packages/render/src/browser/render.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77
import type { Options } from '../shared/options';
88
import { plainTextSelectors } from '../shared/plain-text-selectors';
99
import { pretty } from '../shared/utils/pretty';
10-
import { OptionsContext } from '../shared/useRenderingOptions';
10+
import { setRenderingOptions } from '../shared/useRenderingOptions';
1111

1212
const decoder = new TextDecoder('utf-8');
1313

@@ -53,9 +53,8 @@ export const render = async (
5353
element: React.ReactElement,
5454
options?: Options,
5555
) => {
56-
const suspendedElement = <Suspense>
57-
<OptionsContext.Provider value={options ?? {}}>{element}</OptionsContext.Provider>
58-
</Suspense>;
56+
setRenderingOptions(options?.uniqueRenderId, options)
57+
const suspendedElement = <Suspense>{element}</Suspense>;
5958
const reactDOMServer = await import('react-dom/server');
6059

6160
let html!: string;

packages/render/src/node/render-async-edge.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React from 'react';
66
import { Preview } from '../shared/utils/preview';
77
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
88
import { renderAsync } from './render-async';
9+
import { randomUUID } from 'crypto';
910

1011
type Import = typeof import('react-dom/server') & {
1112
default: typeof import('react-dom/server');
@@ -110,10 +111,39 @@ describe('renderAsync on the edge', () => {
110111
expect(actualOutput).toMatchInlineSnapshot(`
111112
"HELLO, JIM!
112113
113-
Thanks for trying our product."
114+
Thanks for trying our plaintext product."
114115
`);
115116
});
116117

118+
it('successfully passes rendering options when using uniqueRenderId', async () => {
119+
const uniqueRenderId = randomUUID();
120+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
121+
plainText: true,
122+
uniqueRenderId: uniqueRenderId
123+
});
124+
125+
expect(actualOutput).toMatchInlineSnapshot(`
126+
"HELLO, JIM!
127+
128+
Thanks for trying our plaintext product."
129+
`);
130+
});
131+
132+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
133+
const uniqueRenderId1 = randomUUID();
134+
const uniqueRenderId2 = randomUUID();
135+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
136+
plainText: true,
137+
uniqueRenderId: uniqueRenderId2
138+
});
139+
140+
expect(actualOutput).toMatchInlineSnapshot(`
141+
"WELCOME, JIM!
142+
143+
Thanks for trying our product. We're thrilled to have you on board!"
144+
`);
145+
});
146+
117147
it('converts to plain text and removes reserved ID', async () => {
118148
const actualOutput = await renderAsync(<Preview />, {
119149
plainText: true,

packages/render/src/node/render-async-node.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import usePromise from 'react-promise-suspense';
77
import { Preview } from '../shared/utils/preview';
88
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
99
import { renderAsync } from './render-async';
10+
import { randomUUID } from 'crypto';
1011

1112
type Import = typeof import('react-dom/server') & {
1213
default: typeof import('react-dom/server');
@@ -130,10 +131,39 @@ describe('renderAsync on node environments', () => {
130131
expect(actualOutput).toMatchInlineSnapshot(`
131132
"HELLO, JIM!
132133
133-
Thanks for trying our product."
134+
Thanks for trying our plaintext product."
134135
`);
135136
});
136137

138+
it('successfully passes rendering options when using uniqueRenderId', async () => {
139+
const uniqueRenderId = randomUUID();
140+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
141+
plainText: true,
142+
uniqueRenderId: uniqueRenderId
143+
});
144+
145+
expect(actualOutput).toMatchInlineSnapshot(`
146+
"HELLO, JIM!
147+
148+
Thanks for trying our plaintext product."
149+
`);
150+
});
151+
152+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
153+
const uniqueRenderId1 = randomUUID();
154+
const uniqueRenderId2 = randomUUID();
155+
const actualOutput = await renderAsync(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
156+
plainText: true,
157+
uniqueRenderId: uniqueRenderId2
158+
});
159+
160+
expect(actualOutput).toMatchInlineSnapshot(`
161+
"WELCOME, JIM!
162+
163+
Thanks for trying our product. We're thrilled to have you on board!"
164+
`);
165+
});
166+
137167
it('converts to plain text and removes reserved ID', async () => {
138168
const actualOutput = await renderAsync(<Preview />, {
139169
plainText: true,

packages/render/src/node/render-async.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Options } from '../shared/options';
44
import { plainTextSelectors } from '../shared/plain-text-selectors';
55
import { pretty } from '../shared/utils/pretty';
66
import { readStream } from './read-stream';
7-
import { OptionsContext } from '../shared/useRenderingOptions';
7+
import { setRenderingOptions } from '../shared/useRenderingOptions';
88

99
/**
1010
* @deprecated use `render`
@@ -13,9 +13,8 @@ export const renderAsync = async (
1313
element: React.ReactElement,
1414
options?: Options,
1515
) => {
16-
const suspendedElement = <Suspense>
17-
<OptionsContext.Provider value={options ?? {}}>{element}</OptionsContext.Provider>
18-
</Suspense>;
16+
setRenderingOptions(options?.uniqueRenderId, options)
17+
const suspendedElement = <Suspense>{element}</Suspense>;
1918
const reactDOMServer = await import('react-dom/server');
2019

2120
let html!: string;

packages/render/src/node/render-edge.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React from 'react';
66
import { Preview } from '../shared/utils/preview';
77
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
88
import { render } from './render';
9+
import { randomUUID } from 'crypto';
910

1011
type Import = typeof import('react-dom/server') & {
1112
default: typeof import('react-dom/server');
@@ -119,10 +120,39 @@ describe('render on the edge', () => {
119120
expect(actualOutput).toMatchInlineSnapshot(`
120121
"HELLO, JIM!
121122
122-
Thanks for trying our product."
123+
Thanks for trying our plaintext product."
123124
`);
124125
});
125126

127+
it('successfully passes rendering options when using uniqueRenderId', async () => {
128+
const uniqueRenderId = randomUUID();
129+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
130+
plainText: true,
131+
uniqueRenderId: uniqueRenderId
132+
});
133+
134+
expect(actualOutput).toMatchInlineSnapshot(`
135+
"HELLO, JIM!
136+
137+
Thanks for trying our plaintext product."
138+
`);
139+
});
140+
141+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
142+
const uniqueRenderId1 = randomUUID();
143+
const uniqueRenderId2 = randomUUID();
144+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
145+
plainText: true,
146+
uniqueRenderId: uniqueRenderId2
147+
});
148+
149+
expect(actualOutput).toMatchInlineSnapshot(`
150+
"WELCOME, JIM!
151+
152+
Thanks for trying our product. We're thrilled to have you on board!"
153+
`);
154+
});
155+
126156
it('converts to plain text and removes reserved ID', async () => {
127157
const actualOutput = await render(<Preview />, {
128158
plainText: true,

packages/render/src/node/render-node.spec.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import usePromise from 'react-promise-suspense';
77
import { Preview } from '../shared/utils/preview';
88
import { Template, TemplateWithCustomPlainText } from '../shared/utils/template';
99
import { render } from './render';
10+
import { randomUUID } from 'crypto';
1011

1112
type Import = typeof import('react-dom/server') & {
1213
default: typeof import('react-dom/server');
@@ -148,7 +149,36 @@ describe('render on node environments', () => {
148149
expect(actualOutput).toMatchInlineSnapshot(`
149150
"HELLO, JIM!
150151
151-
Thanks for trying our product."
152+
Thanks for trying our plaintext product."
153+
`);
154+
});
155+
156+
it('successfully passes rendering options when using uniqueRenderId', async () => {
157+
const uniqueRenderId = randomUUID();
158+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId} />, {
159+
plainText: true,
160+
uniqueRenderId: uniqueRenderId
161+
});
162+
163+
expect(actualOutput).toMatchInlineSnapshot(`
164+
"HELLO, JIM!
165+
166+
Thanks for trying our plaintext product."
167+
`);
168+
});
169+
170+
it('fails to pass rendering options when uniqueRenderId does not match', async () => {
171+
const uniqueRenderId1 = randomUUID();
172+
const uniqueRenderId2 = randomUUID();
173+
const actualOutput = await render(<TemplateWithCustomPlainText firstName="Jim" uniqueRenderId={uniqueRenderId1} />, {
174+
plainText: true,
175+
uniqueRenderId: uniqueRenderId2
176+
});
177+
178+
expect(actualOutput).toMatchInlineSnapshot(`
179+
"WELCOME, JIM!
180+
181+
Thanks for trying our product. We're thrilled to have you on board!"
152182
`);
153183
});
154184

packages/render/src/node/render.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import type { Options } from '../shared/options';
44
import { plainTextSelectors } from '../shared/plain-text-selectors';
55
import { pretty } from '../shared/utils/pretty';
66
import { readStream } from './read-stream';
7-
import { OptionsContext } from '../shared/useRenderingOptions';
7+
import { setRenderingOptions } from '../shared/useRenderingOptions';
88

99
export const render = async (
1010
element: React.ReactElement,
1111
options?: Options,
1212
) => {
13-
const suspendedElement = <Suspense>
14-
<OptionsContext.Provider value={options ?? {}}>{element}</OptionsContext.Provider>
15-
</Suspense>;
13+
setRenderingOptions(options?.uniqueRenderId, options)
14+
const suspendedElement = <Suspense>{element}</Suspense>;
1615
const reactDOMServer = await import('react-dom/server');
1716

1817
let html!: string;

packages/render/src/shared/options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { HtmlToTextOptions } from 'html-to-text';
22

33
export type Options = {
44
pretty?: boolean;
5+
uniqueRenderId?: string;
56
} & (
67
| {
78
plainText?: false;
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { createContext, useContext } from "react";
21
import { Options } from "./options";
32

4-
export const OptionsContext = createContext<Options>({});
3+
const opts: Record<string, Options> = {}
54

6-
export function useRenderingOptions() {
7-
const opts = useContext(OptionsContext);
8-
return opts;
5+
export function setRenderingOptions(uniqueRenderId: string | undefined, options: Options | undefined) {
6+
opts[uniqueRenderId ?? ""] = options ?? ({} as Options);
7+
}
8+
9+
export function useRenderingOptions(uniqueRenderId?: string) {
10+
return opts[uniqueRenderId ?? ""];
911
}

0 commit comments

Comments
 (0)