From 706bc088ac6020b814ed32a52478798234e8efcb Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 26 Aug 2025 17:32:36 +0200 Subject: [PATCH] fix fragment issue --- package.json | 2 +- src/client/layout/Tabs.tsx | 2 +- src/vite/utils/inject-source.test.ts | 58 ++++++++++++++++++++++++++++ src/vite/utils/inject-source.ts | 15 +++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b26819fe..35ac9ebc 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "react-router-devtools", "description": "Devtools for React Router - debug, trace, find hydration errors, catch bugs and inspect server/client data with react-router-devtools", "author": "Alem Tuzlak", - "version": "5.1.0", + "version": "5.1.1", "license": "MIT", "keywords": [ "react-router", diff --git a/src/client/layout/Tabs.tsx b/src/client/layout/Tabs.tsx index 96814d01..2e0b6f32 100644 --- a/src/client/layout/Tabs.tsx +++ b/src/client/layout/Tabs.tsx @@ -90,7 +90,7 @@ const Tabs = ({ plugins, setIsOpen }: TabsProps) => { } const getErrorCount = () => { - return htmlErrors.length + (window.HYDRATION_OVERLAY.ERROR ? 1 : 0) + return htmlErrors.length + (window.HYDRATION_OVERLAY?.ERROR ? 1 : 0) } const hasErrors = getErrorCount() > 0 diff --git a/src/vite/utils/inject-source.test.ts b/src/vite/utils/inject-source.test.ts index 3451f129..60c4d4fd 100644 --- a/src/vite/utils/inject-source.test.ts +++ b/src/vite/utils/inject-source.test.ts @@ -6,6 +6,64 @@ const removeEmptySpace = (str: string) => { } describe("inject source", () => { + it("shouldn't augment react fragments", () => { + const output = removeEmptySpace( + addSourceToJsx( + ` + export const Route = createFileRoute("/test")({ + component: function() { return <>Hello World }, + }) + `, + "test.jsx" + ).code + ) + expect(output).toBe( + removeEmptySpace(` + export const Route = createFileRoute("/test")({ + component: function() { return <>Hello World }, + }) + `) + ) + }) + + it("shouldn't augment react fragments if they start with Fragment ", () => { + const output = removeEmptySpace( + addSourceToJsx( + ` + export const Route = createFileRoute("/test")({ + component: function() { return Hello World }, + }) + `, + "test.jsx" + ).code + ) + expect(output).toBe( + removeEmptySpace(` + export const Route = createFileRoute("/test")({ + component: function() { return Hello World }, + }) + `) + ) + }) + it("shouldn't augment react fragments if they start with React.Fragment ", () => { + const output = removeEmptySpace( + addSourceToJsx( + ` + export const Route = createFileRoute("/test")({ + component: function() { return Hello World }, + }) + `, + "test.jsx" + ).code + ) + expect(output).toBe( + removeEmptySpace(` + export const Route = createFileRoute("/test")({ + component: function() { return Hello World }, + }) + `) + ) + }) describe("FunctionExpression", () => { it("should work with deeply nested custom JSX syntax", () => { const output = removeEmptySpace( diff --git a/src/vite/utils/inject-source.ts b/src/vite/utils/inject-source.ts index 25dc3976..3b9455ea 100644 --- a/src/vite/utils/inject-source.ts +++ b/src/vite/utils/inject-source.ts @@ -82,12 +82,27 @@ const getPropsNameFromFunctionDeclaration = ( return propsName } +const getNameOfElement = (element: t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName): string => { + if (element.type === "JSXIdentifier") { + return element.name + } + if (element.type === "JSXMemberExpression") { + return `${getNameOfElement(element.object)}.${getNameOfElement(element.property)}` + } + + return `${element.namespace.name}:${element.name.name}` +} + const transformJSX = (element: NodePath, propsName: string | null, file: string) => { const loc = element.node.loc if (!loc) return const line = loc.start.line const column = loc.start.column + const nameOfElement = getNameOfElement(element.node.name) + if (nameOfElement === "Fragment" || nameOfElement === "React.Fragment") { + return + } const hasDataSource = element.node.attributes.some( (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "data-rrdt-source"