Skip to content

Commit b4b2373

Browse files
authored
fix(react-email): Non-emails files being rendered when hot reloading (#2095)
1 parent 5c6150d commit b4b2373

File tree

5 files changed

+55
-7
lines changed

5 files changed

+55
-7
lines changed

.changeset/six-parts-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-email": patch
3+
---
4+
5+
Fix non-email files being rendered during hot reloading

packages/react-email/src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,15 @@ export const setupHotreloading = async (
2828
const reload = debounce(() => {
2929
// we detect these using the useHotreload hook on the Next app
3030
clients.forEach((client) => {
31-
client.emit('reload', changes);
31+
client.emit(
32+
'reload',
33+
changes.filter((change) =>
34+
// Ensures only changes inside the emails directory are emitted
35+
path
36+
.resolve(absolutePathToEmailsDirectory, change.filename)
37+
.startsWith(absolutePathToEmailsDirectory),
38+
),
39+
);
3240
});
3341

3442
changes = [];

packages/react-email/src/hooks/use-email-rendering-result.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,24 @@ export const useEmailRenderingResult = (
2323
// eslint-disable-next-line react-hooks/rules-of-hooks
2424
useHotreload(async (changes) => {
2525
for await (const change of changes) {
26-
const slugForChangedFile =
26+
const relativePathForChangedFile =
2727
// ex: apple-receipt.tsx
2828
// it will be the path relative to the emails directory, so it is already
2929
// going to be equivalent to the slug
3030
change.filename;
3131

3232
if (
33-
containsEmailTemplate(slugForChangedFile, emailsDirectoryMetadata)
33+
!containsEmailTemplate(
34+
relativePathForChangedFile,
35+
emailsDirectoryMetadata,
36+
)
3437
) {
3538
continue;
3639
}
3740

38-
const pathForChangedEmail =
39-
await getEmailPathFromSlug(slugForChangedFile);
41+
const pathForChangedEmail = await getEmailPathFromSlug(
42+
relativePathForChangedFile,
43+
);
4044

4145
const newRenderingResult = await renderEmailByPath(
4246
pathForChangedEmail,

packages/react-email/src/utils/contains-email-template.spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
import path from 'node:path';
2-
import { containsEmailTemplate } from './contains-email-template';
2+
import {
3+
containsEmailTemplate,
4+
removeFilenameExtension,
5+
} from './contains-email-template';
6+
7+
describe('removeFilenameExtension()', async () => {
8+
it('should work with a single .', () => {
9+
expect(removeFilenameExtension('email-template.tsx')).toBe(
10+
'email-template',
11+
);
12+
});
13+
14+
it('should work with an example test file', () => {
15+
expect(removeFilenameExtension('email-template.spec.tsx')).toBe(
16+
'email-template.spec',
17+
);
18+
});
19+
20+
it('should do nothing when there is no extension', () => {
21+
expect(removeFilenameExtension('email-template')).toBe('email-template');
22+
});
23+
});
324

425
test('containsEmailTemplate()', async () => {
526
const emailsDirectoryPath = path.resolve(

packages/react-email/src/utils/contains-email-template.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import type { EmailsDirectory } from './get-emails-directory-metadata';
22

3+
export const removeFilenameExtension = (filename: string): string => {
4+
const parts = filename.split('.');
5+
6+
if (parts.length > 1) {
7+
return parts.slice(0, -1).join('.');
8+
}
9+
10+
return filename;
11+
};
12+
313
export const containsEmailTemplate = (
414
relativeEmailPath: string,
515
directory: EmailsDirectory,
@@ -9,7 +19,7 @@ export const containsEmailTemplate = (
919
.split('/')
1020
.filter(Boolean);
1121
if (remainingSegments.length === 1) {
12-
const emailFilename = remainingSegments[0]!;
22+
const emailFilename = removeFilenameExtension(remainingSegments[0]!);
1323
return directory.emailFilenames.includes(emailFilename);
1424
}
1525
const subDirectory = directory.subDirectories.find(

0 commit comments

Comments
 (0)