@@ -128,11 +128,12 @@ function getSafeVariableName(context: Rule.RuleContext, name: string) {
128
128
}
129
129
130
130
// Eslint Auto-fix logic, functional components/hooks only
131
- export function fixBasedOnMessageId ( node : Rule . Node , messageId : keyof typeof MessagesRequireUseMemo , fixer : Rule . RuleFixer , context : Rule . RuleContext , reactImportData : ReactImportInformation ) {
131
+ export function fixBasedOnMessageId ( node : Rule . Node | TSESTree . JSXElement , messageId : keyof typeof MessagesRequireUseMemo , fixer : Rule . RuleFixer , context : Rule . RuleContext , reactImportData : ReactImportInformation ) {
132
132
const sourceCode = context . getSourceCode ( ) ;
133
133
let hook = messageIdToHookDict [ messageId ] || 'useMemo' ;
134
134
const isObjExpression = node . type === 'ObjectExpression' ;
135
- const parentIsVariableDeclarator = node . parent . type === 'VariableDeclarator' ;
135
+ const isJSXElement = node . type === 'JSXElement' ;
136
+ const parentIsVariableDeclarator = ( node as Rule . Node ) . parent . type === 'VariableDeclarator' ;
136
137
const isArrowFunctionExpression = node . type === 'ArrowFunctionExpression' ;
137
138
const isFunctionExpression = node . type === 'FunctionExpression' ;
138
139
const isCorrectableFunctionExpression = isFunctionExpression || ( isArrowFunctionExpression && parentIsVariableDeclarator ) ;
@@ -142,8 +143,9 @@ export function fixBasedOnMessageId(node: Rule.Node, messageId: keyof typeof Mes
142
143
switch ( messageId ) {
143
144
case 'function-usecallback-props' :
144
145
case 'object-usememo-props' :
146
+ case 'jsx-usememo-props' :
145
147
case 'usememo-const' : {
146
- let variableDeclaration = node . type === 'VariableDeclaration' ? node : findParentType ( node , 'VariableDeclaration' ) as TSESTree . VariableDeclaration ;
148
+ let variableDeclaration = node . type === 'VariableDeclaration' ? node : findParentType ( node as Rule . Node , 'VariableDeclaration' ) as TSESTree . VariableDeclaration ;
147
149
148
150
// Check if it is a hook being stored in let/var, change to const if so
149
151
if ( variableDeclaration && variableDeclaration . kind !== 'const' ) {
@@ -157,28 +159,28 @@ export function fixBasedOnMessageId(node: Rule.Node, messageId: keyof typeof Mes
157
159
}
158
160
}
159
161
// If it's an dynamic object - Add useMemo/Callback
160
- if ( ( isObjExpression || isCorrectableFunctionExpression ) ) {
162
+ if ( ( isObjExpression || isJSXElement || isCorrectableFunctionExpression ) ) {
161
163
162
164
const importStatementFixes = addReactImports ( context , isCorrectableFunctionExpression ? 'useCallback' : 'useMemo' , reactImportData , fixer ) ;
163
165
importStatementFixes && fixes . push ( importStatementFixes ) ;
164
- const fixed = isCorrectableFunctionExpression ? fixFunction ( node as TSESTree . FunctionExpression , context ) : `useMemo(() => (${ sourceCode . getText ( node ) } ), [])` ;
166
+ const fixed = isCorrectableFunctionExpression ? fixFunction ( node as TSESTree . FunctionExpression , context ) : `useMemo(() => (${ sourceCode . getText ( node as Rule . Node ) } ), [])` ;
165
167
const parent = node . parent as unknown as TSESTree . JSXExpressionContainer ;
166
168
// Means we have a object expression declared directly in jsx
167
169
if ( parent . type === 'JSXExpressionContainer' ) {
168
170
const parentPropName = ( parent ?. parent as TSESTree . JSXAttribute ) ?. name ?. name . toString ( ) ;
169
171
const newVarName = getSafeVariableName ( context , parentPropName ) ;
170
- const returnStatement = findParentType ( node , 'ReturnStatement' ) as TSESTree . ReturnStatement ;
172
+ const returnStatement = findParentType ( node as Rule . Node , 'ReturnStatement' ) as TSESTree . ReturnStatement ;
171
173
172
174
if ( returnStatement ) {
173
175
const indentationLevel = sourceCode . lines [ returnStatement . loc . start . line - 1 ] . search ( / \S / ) ;
174
176
const indentation = ' ' . repeat ( indentationLevel ) ;
175
177
// Creates a declaration for the variable and inserts it before the return statement
176
178
fixes . push ( fixer . insertTextBeforeRange ( returnStatement . range , `const ${ newVarName } = ${ fixed } ;\n${ indentation } ` ) ) ;
177
179
// Replaces the old inline object expression with the variable name
178
- fixes . push ( fixer . replaceText ( node , newVarName ) ) ;
180
+ fixes . push ( fixer . replaceText ( node as Rule . Node , newVarName ) ) ;
179
181
}
180
182
} else {
181
- fixes . push ( fixer . replaceText ( node , fixed ) ) ;
183
+ fixes . push ( fixer . replaceText ( node as Rule . Node , fixed ) ) ;
182
184
}
183
185
184
186
}
@@ -194,7 +196,7 @@ export function fixBasedOnMessageId(node: Rule.Node, messageId: keyof typeof Mes
194
196
}
195
197
196
198
// Simpler cases bellow, all of them are just adding useMemo/Callback
197
- let fixed = `${ hook } (() => ${ isObjExpression ? "(" : '' } ${ sourceCode . getText ( node as unknown as ESTree . Node ) } ${ isObjExpression ? ")" : '' } , [])` ;
199
+ let fixed = `${ hook } (() => ${ isObjExpression || isJSXElement ? "(" : '' } ${ sourceCode . getText ( node as unknown as ESTree . Node ) } ${ isObjExpression ? ")" : '' } , [])` ;
198
200
const importStatementFixes = addReactImports ( context , hook , reactImportData , fixer ) ;
199
201
importStatementFixes && fixes . push ( importStatementFixes ) ;
200
202
@@ -208,7 +210,7 @@ export function fixBasedOnMessageId(node: Rule.Node, messageId: keyof typeof Mes
208
210
if ( 'computed' in node && ( node as any ) ?. computed ?. type === 'ArrowFunctionExpression' ) {
209
211
fixes . push ( fixer . replaceText ( ( node as any ) . computed , fixed ) as Rule . Fix ) ;
210
212
} else {
211
- fixes . push ( fixer . replaceText ( node , fixed ) as Rule . Fix ) ;
213
+ fixes . push ( fixer . replaceText ( node as Rule . Node , fixed ) as Rule . Fix ) ;
212
214
}
213
215
return fixes ;
214
216
}
0 commit comments