Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@arthurgeron/eslint-plugin-react-usememo

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arthurgeron/eslint-plugin-react-usememo - npm Package Compare versions

Comparing version 2.0.1 to 2.1.0

91

dist/index.js

@@ -128,2 +128,37 @@ 'use strict';

}
function addReactImports(context, kind, reactImportData, fixer) {
var _a, _b, _c, _d, _e, _f;
var sourceCode = context.getSourceCode();
var importsDisabled = ((_c = (_b = (_a = context.options) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.fix) === null || _c === void 0 ? void 0 : _c.addImports) === false;
var specifier = undefined;
if (importsDisabled) {
return;
}
if (!reactImportData["".concat(kind, "Imported")]) {
// Create a new ImportSpecifier for useMemo/useCallback hook.
specifier = {
type: 'ImportSpecifier',
imported: { type: 'Identifier', name: kind },
local: { type: 'Identifier', name: kind }
};
if (reactImportData.importDeclaration) {
reactImportData.importDeclaration.specifiers.push(specifier);
return fixer.insertTextAfter(reactImportData.importDeclaration.specifiers[reactImportData.importDeclaration.specifiers.length - 2], ", ".concat(kind));
}
}
// If React is not imported, create a new ImportDeclaration for it.
if (!reactImportData.reactImported && !reactImportData.importDeclaration) {
reactImportData.importDeclaration = {
type: 'ImportDeclaration',
specifiers: [specifier],
source: { type: 'Literal', value: 'react' }
};
reactImportData.reactImported = true;
reactImportData["".concat(kind, "Imported")] = true;
((_f = (_e = (_d = sourceCode.ast.body[0]) === null || _d === void 0 ? void 0 : _d.leadingComments) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.value) || "";
// Add an extra new line before const component and use indentSpace for proper spacing.
return fixer.insertTextBeforeRange([0, 0], "import { ".concat(kind, " } from 'react';\n"));
}
return;
}
function getIsHook(node) {

@@ -160,3 +195,3 @@ if (node.type === "Identifier") {

var funcParams = params.map(function (node) { return sourceCode.getText(node); });
var fixedCode = "React.useCallback((".concat(funcParams.join(', '), ") => ").concat(funcBody, ", [])").concat(shouldSetName ? ';' : '');
var fixedCode = "useCallback((".concat(funcParams.join(', '), ") => ").concat(funcBody, ", [])").concat(shouldSetName ? ';' : '');
if (shouldSetName && ((_a = node === null || node === void 0 ? void 0 : node.id) === null || _a === void 0 ? void 0 : _a.name)) {

@@ -179,3 +214,3 @@ var name_2 = (_b = node === null || node === void 0 ? void 0 : node.id) === null || _b === void 0 ? void 0 : _b.name;

// Eslint Auto-fix logic, functional components/hooks only
function fixBasedOnMessageId(node, messageId, fixer, context) {
function fixBasedOnMessageId(node, messageId, fixer, context, reactImportData) {
var _a, _b, _c, _d;

@@ -189,2 +224,3 @@ var sourceCode = context.getSourceCode();

var isCorrectableFunctionExpression = isFunctionExpression || (isArrowFunctionExpression && parentIsVariableDeclarator);
var fixes = [];
// Determine what type of behavior to follow according to the error message

@@ -195,8 +231,6 @@ switch (messageId) {

case 'usememo-const': {
var sourceCode_1 = context.getSourceCode();
var variableDeclaration = node.type === 'VariableDeclaration' ? node : findParentType(node, 'VariableDeclaration');
var fixes = [];
// Check if it is a hook being stored in let/var, change to const if so
if (variableDeclaration && variableDeclaration.kind !== 'const') {
var tokens = sourceCode_1.getTokens(variableDeclaration);
var tokens = sourceCode.getTokens(variableDeclaration);
var letKeywordToken = tokens === null || tokens === void 0 ? void 0 : tokens[0];

@@ -209,3 +243,5 @@ if ((letKeywordToken === null || letKeywordToken === void 0 ? void 0 : letKeywordToken.value) !== 'const') {

if ((isObjExpression || isCorrectableFunctionExpression)) {
var fixed_1 = isCorrectableFunctionExpression ? fixFunction(node, context) : "React.useMemo(() => (".concat(sourceCode_1.getText(node), "), [])");
var importStatementFixes_1 = addReactImports(context, isCorrectableFunctionExpression ? 'useCallback' : 'useMemo', reactImportData, fixer);
importStatementFixes_1 && fixes.push(importStatementFixes_1);
var fixed_1 = isCorrectableFunctionExpression ? fixFunction(node, context) : "useMemo(() => (".concat(sourceCode.getText(node), "), [])");
var parent_1 = node.parent;

@@ -218,3 +254,3 @@ // Means we have a object expression declared directly in jsx

if (returnStatement) {
var indentationLevel = sourceCode_1.lines[returnStatement.loc.start.line - 1].search(/\S/);
var indentationLevel = sourceCode.lines[returnStatement.loc.start.line - 1].search(/\S/);
var indentation = ' '.repeat(indentationLevel);

@@ -241,3 +277,5 @@ // Creates a declaration for the variable and inserts it before the return statement

// Simpler cases bellow, all of them are just adding useMemo/Callback
var fixed = "React.".concat(hook, "(() => ").concat(isObjExpression ? "(" : '').concat(sourceCode.getText(node)).concat(isObjExpression ? ")" : '', ", [])");
var fixed = "".concat(hook, "(() => ").concat(isObjExpression ? "(" : '').concat(sourceCode.getText(node)).concat(isObjExpression ? ")" : '', ", [])");
var importStatementFixes = addReactImports(context, hook, reactImportData, fixer);
importStatementFixes && fixes.push(importStatementFixes);
if (node.type === 'FunctionDeclaration') {

@@ -250,7 +288,8 @@ var _node = node;

if ('computed' in node && ((_d = node === null || node === void 0 ? void 0 : node.computed) === null || _d === void 0 ? void 0 : _d.type) === 'ArrowFunctionExpression') {
return fixer.replaceText(node.computed, fixed);
fixes.push(fixer.replaceText(node.computed, fixed));
}
else {
return fixer.replaceText(node, fixed);
fixes.push(fixer.replaceText(node, fixed));
}
return fixes;
}

@@ -463,8 +502,8 @@

var MessagesRequireUseMemoChildren = {
"object-usememo-children": "Object literal should be wrapped in React.useMemo() when used as children",
"array-usememo-children": "Array literal should be wrapped in React.useMemo() when used as children",
"instance-usememo-children": "Object instantiation should be wrapped in React.useMemo() when used as children",
"jsx-usememo-children": "JSX should be wrapped in React.useMemo() when used as children",
"function-usecallback-children": "Function definition should be wrapped in React.useCallback() when used as children",
"unknown-usememo-children": "Unknown value may need to be wrapped in React.useMemo() when used as children",
"object-usememo-children": "Object literal should be wrapped in React's useMemo() when used as children",
"array-usememo-children": "Array literal should be wrapped in React's useMemo() when used as children",
"instance-usememo-children": "Object instantiation should be wrapped in React's useMemo() when used as children",
"jsx-usememo-children": "JSX should be wrapped in React's useMemo() when used as children",
"function-usecallback-children": "Function definition should be wrapped in useCallback() when used as children",
"unknown-usememo-children": "Unknown value may need to be wrapped in React's useMemo() when used as children",
"usememo-const": "useMemo/useCallback return value should be assigned to a `const` to prevent reassignment"

@@ -485,3 +524,5 @@ };

type: "object",
properties: { strict: { type: "boolean" }, checkHookReturnObject: { type: "boolean" }, checkHookCalls: { type: "boolean" }, ignoredHookCallsNames: { type: "object" } },
properties: { strict: { type: "boolean" }, checkHookReturnObject: { type: "boolean" }, checkHookCalls: { type: "boolean" }, ignoredHookCallsNames: { type: "object" }, fix: {
addImports: "boolean"
} },
additionalProperties: false

@@ -493,2 +534,7 @@ },

var isClass = false;
var importData = {
reactImported: false,
useMemoImported: false,
useCallbackImported: false
};
function report(node, messageId) {

@@ -499,3 +545,3 @@ context.report({ node: node, messageId: messageId, fix: function (fixer) {

}
return fixBasedOnMessageId(node, messageId, fixer, context);
return fixBasedOnMessageId(node, messageId, fixer, context, importData);
} });

@@ -533,2 +579,11 @@ }

},
ImportDeclaration: function (node) {
if (node.source.value === 'react') {
importData.reactImported = true;
importData.importDeclaration = node;
var specifiers = node.specifiers;
importData.useMemoImported = specifiers.some(function (specifier) { return specifier.local.name === 'useMemo'; });
importData.useCallbackImported = specifiers.some(function (specifier) { return specifier.local.name === 'useCallback'; });
}
},
ReturnStatement: function (node) {

@@ -535,0 +590,0 @@ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;

2

package.json
{
"name": "@arthurgeron/eslint-plugin-react-usememo",
"version": "2.0.1",
"version": "2.1.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -41,3 +41,3 @@ # ESLint-Plugin-React-UseMemo

```
> For more details, please refer to React Native's [documentation](https://reactnative.dev/docs/0.61/optimizing-flatlist-configuration#avoid-anonymous-function-on-renderitem) on the importance of using static or memoized props for complex children.
> For more details, please refer to React's [documentation](https://react.dev/reference/react/useMemo) on hooks, re-rendering and memoization.

@@ -79,3 +79,3 @@ ## Installation

For detailed examples, options available for this rule, and information about the autofix functionality, please refer to our rules documentation.
For detailed examples, options available for this rule, and information about the autofix functionality, please refer to our [rules documentation](https://github.com/arthurgeron/eslint-plugin-react-usememo/blob/main/docs/rules/require-usememo.md).

@@ -93,2 +93,2 @@ ## Rule #2: `require-memo`

## Conclusion
By efficiently using `useMemo`, `useCallback`, and `React.memo()`, we can optimize our React and React Native applications. It allows us to control the re-calculation and re-rendering of components, offering better scalability and performance.
By efficiently using `useMemo`, `useCallback`, and `React.memo()`, we can optimize our React and React Native applications. It allows us to control the re-calculation and re-rendering of components, offering better scalability and performance.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc