diff --git a/codemods/react/19/replace-default-props/.codemodrc.json b/codemods/react/19/replace-default-props/.codemodrc.json index 30d2d25b..4726df91 100644 --- a/codemods/react/19/replace-default-props/.codemodrc.json +++ b/codemods/react/19/replace-default-props/.codemodrc.json @@ -1,7 +1,7 @@ { "$schema": "https://codemod-utils.s3.us-west-1.amazonaws.com/configuration_schema.json", "name": "react/19/replace-default-props", - "version": "1.0.2", + "version": "1.0.3", "engine": "jscodeshift", "private": false, "arguments": [], diff --git a/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-input.jsx b/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-input.jsx new file mode 100644 index 00000000..92a9d9b4 --- /dev/null +++ b/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-input.jsx @@ -0,0 +1,8 @@ +const Button = ({ size, color }) => { + return ; +}; + +Button.defaultProps = { + size: "16px", + color: "blue", +}; \ No newline at end of file diff --git a/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-output.jsx b/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-output.jsx new file mode 100644 index 00000000..154516b8 --- /dev/null +++ b/codemods/react/19/replace-default-props/__testfixtures__/button-jsx-example-output.jsx @@ -0,0 +1,3 @@ +const Button = ({ size = "16px", color = "blue" }) => { + return ; +}; \ No newline at end of file diff --git a/codemods/react/19/replace-default-props/__testfixtures__/nested-destructuring.output.tsx b/codemods/react/19/replace-default-props/__testfixtures__/nested-destructuring.output.tsx index f3350de4..5c669c36 100644 --- a/codemods/react/19/replace-default-props/__testfixtures__/nested-destructuring.output.tsx +++ b/codemods/react/19/replace-default-props/__testfixtures__/nested-destructuring.output.tsx @@ -1,9 +1,7 @@ -const Card = ({ - user: { name, age } = { - name: "Unknown", - age: 0, - }, -}) => { +const Card = ({ user: { name, age } = { + name: "Unknown", + age: 0, +} }) => { return (

{name}

diff --git a/codemods/react/19/replace-default-props/__testfixtures__/with-functions.output.tsx b/codemods/react/19/replace-default-props/__testfixtures__/with-functions.output.tsx index 9545553d..b90f38f1 100644 --- a/codemods/react/19/replace-default-props/__testfixtures__/with-functions.output.tsx +++ b/codemods/react/19/replace-default-props/__testfixtures__/with-functions.output.tsx @@ -1,6 +1,3 @@ -const List = ({ - items = [], - renderItem = (item) =>
  • {item}
  • , -}) => { +const List = ({ items = [], renderItem = (item) =>
  • {item}
  • }) => { return ; }; diff --git a/codemods/react/19/replace-default-props/src/index.ts b/codemods/react/19/replace-default-props/src/index.ts index 89fe2380..99fc3720 100644 --- a/codemods/react/19/replace-default-props/src/index.ts +++ b/codemods/react/19/replace-default-props/src/index.ts @@ -6,6 +6,7 @@ import type { JSCodeshift, MemberExpression, ObjectProperty, + Property, } from "jscodeshift"; import { getFunctionName } from "@codemod.com/codemod-utils/dist/jscodeshift/function.js"; @@ -36,7 +37,7 @@ const getComponentStaticPropValue = ( const buildPropertyWithDefaultValue = ( j: JSCodeshift, - property: ObjectProperty, + property: ObjectProperty | Property, defaultValue: any, ) => { // Special handling for nested destructuring patterns @@ -84,13 +85,11 @@ export default function transform( defaultPropsRight.properties?.forEach((property) => { if ( - !j.ObjectProperty.check(property) || - !j.Identifier.check(property.key) + (j.Property.check(property) || j.ObjectProperty.check(property)) && + j.Identifier.check(property.key) ) { - return; + defaultPropsMap.set(property.key.name, property.value); } - - defaultPropsMap.set(property.key.name, property.value); }); const propsArg = path.value.params.at(0); @@ -98,19 +97,17 @@ export default function transform( if (j.ObjectPattern.check(propsArg)) { propsArg.properties.forEach((property) => { if ( - !j.ObjectProperty.check(property) || - !j.Identifier.check(property.key) || - j.AssignmentPattern.check(property.value) + (j.Property.check(property) || j.ObjectProperty.check(property)) && + j.Identifier.check(property.key) ) { - return; - } - if (defaultPropsMap.has(property.key.name)) { - isDirty = true; - property.value = buildPropertyWithDefaultValue( - j, - property, - defaultPropsMap.get(property.key.name), - ); + if (defaultPropsMap.has(property.key.name)) { + isDirty = true; + property.value = buildPropertyWithDefaultValue( + j, + property, + defaultPropsMap.get(property.key.name), + ); + } } }); } diff --git a/codemods/react/19/replace-default-props/test/test.ts b/codemods/react/19/replace-default-props/test/test.ts index c72c203e..29b2e46f 100644 --- a/codemods/react/19/replace-default-props/test/test.ts +++ b/codemods/react/19/replace-default-props/test/test.ts @@ -208,4 +208,35 @@ describe("react/19/replace-default-props", () => { OUTPUT.replace(/W/gm, ""), ); }); + + it("should correctly transform when props are not destructured", async () => { + const INPUT = await readFile( + join(__dirname, "..", "__testfixtures__/button-jsx-example-input.jsx"), + "utf-8", + ); + const OUTPUT = await readFile( + join(__dirname, "..", "__testfixtures__/button-jsx-example-output.jsx"), + "utf-8", + ); + + const actualOutput = transform( + { + path: "index.js", + source: INPUT, + }, + buildApi("jsx"), + ); + + const fs = require("node:fs"); + fs.writeFileSync( + join(__dirname, "..", "__testfixtures__/button-jsx-example-output.jsx"), + actualOutput, + ); + + assert.deepEqual( + actualOutput?.replace(/W/gm, ""), + OUTPUT.replace(/W/gm, ""), + ); + }); }); +