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 0.0.4 to 0.1.0

28

dist/index.js

@@ -105,6 +105,9 @@ 'use strict';

"object-usememo-props": "Object literal should be wrapped in useMemo() or be static when used as a prop",
"object-class-memo-props": "Object literal should com from state or be static when used as a prop",
"object-usememo-deps": "Object literal should be wrapped in useMemo() or be static when used as a hook dependency",
"array-usememo-props": "Array literal should be wrapped in useMemo() or be static when used as a prop",
"array-class-memo-props": "Array literal should be from state and declared in state, constructor, getDerivedStateFromProps or statically when used as a prop",
"array-usememo-deps": "Array literal should be wrapped in useMemo() or be static when used as a hook dependency",
"instance-usememo-props": "Object instantiation should be wrapped in useMemo() or be static when used as a prop",
"instance-class-memo-props": "Object instantiation should be done in state, constructor, getDerivedStateFromProps or statically when used as a prop",
"instance-usememo-deps": "Object instantiation should be wrapped in useMemo() or be static when used as a hook dependency",

@@ -114,4 +117,6 @@ "jsx-usememo-props": "JSX should be wrapped in useMemo() when used as a prop",

"function-usecallback-props": "Function definition should be wrapped in useCallback() or be static when used as a prop",
"function-class-props": "Function definition should declared as a class property or statically when used as a prop",
"function-usecallback-deps": "Function definition should be wrapped in useCallback() or be static when used as a hook dependency",
"unknown-usememo-props": "Unknown value may need to be wrapped in useMemo() when used as a prop",
"unknown-class-memo-props": "Unknown value should be declared in state, constructor, getDerivedStateFromProps or statically when used as a prop",
"unknown-usememo-deps": "Unknown value may need to be wrapped in useMemo() when used as a hook dependency",

@@ -240,2 +245,3 @@ "usememo-const": "useMemo/useCallback return value should be assigned to a const to prevent reassignment"

create: function (context) {
var isClass = false;
function report(node, messageId) {

@@ -260,12 +266,12 @@ context.report({ node: node, messageId: messageId });

case MemoStatus.UnmemoizedObject:
report(node, "object-usememo-props");
report(node, isClass ? "object-class-memo-props" : "object-usememo-props");
return;
case MemoStatus.UnmemoizedArray:
report(node, "array-usememo-props");
report(node, isClass ? "array-class-memo-props" : "array-usememo-props");
return;
case MemoStatus.UnmemoizedNew:
report(node, "instance-usememo-props");
report(node, isClass ? "instance-class-memo-props" : "instance-usememo-props");
return;
case MemoStatus.UnmemoizedFunction:
report(node, "function-usecallback-props");
report(node, isClass ? 'instance-class-memo-props' : "function-usecallback-props");
return;

@@ -275,6 +281,9 @@ case MemoStatus.UnmemoizedFunctionCall:

if ((_b = (_a = context.options) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.strict) {
report(node, "unknown-usememo-props");
report(node, isClass ? "unknown-class-memo-props" : "unknown-usememo-props");
}
return;
case MemoStatus.UnmemoizedJSX:
if (isClass) {
return;
}
report(node, "jsx-usememo-props");

@@ -297,2 +306,5 @@ return;

},
ClassDeclaration: function () {
isClass = true;
},
CallExpression: function (node) {

@@ -352,2 +364,3 @@ var _a, _b;

create: function (context) {
var isClass = false;
function report(node, messageId) {

@@ -357,6 +370,9 @@ context.report({ node: node, messageId: messageId });

return {
ClassDeclaration: function () {
isClass = true;
},
JSXElement: function (node) {
var _a, _b;
var _c = node, children = _c.children, openingElement = _c.openingElement;
if (!isComplexComponent(openingElement))
if (isClass || !isComplexComponent(openingElement))
return;

@@ -363,0 +379,0 @@ for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {

{
"name": "@arthurgeron/eslint-plugin-react-usememo",
"version": "0.0.4",
"version": "0.1.0",
"description": "",

@@ -13,2 +13,4 @@ "main": "dist/index.js",

"devDependencies": {
"@commitlint/cli": "17.0.3",
"@commitlint/config-conventional": "17.0.3",
"@jest/types": "28.1.3",

@@ -32,2 +34,3 @@ "@rollup/plugin-node-resolve": "13.3.0",

"build": "rm -rf dist && rollup -c",
"prepare": "husky install",
"prepublish:public": "npm run build",

@@ -34,0 +37,0 @@ "publish:public": "npm publish --access public",

@@ -53,9 +53,44 @@ # eslint-plugin-react-usememo

function renderItem({ item }) {
return <Text>item.name</Text>;
return (<Text>item.name</Text>);
}
// Data isn't redeclared each ender but `[]` is
<FlatList renderItem={renderItem} data={data ?? []} />
return (<FlatList renderItem={renderItem} data={data ?? []} />);
}
```
## **Incorrect** (class component)
```JavaScript
class Component() {
constructor(props) {
super(props);
this.state = {
data: undefined,
propDrivenData: props.,
};
}
// This will NOT be redeclared each render
getItemName(item) {
return item.name;
}
render() {
// This function will be redeclared each render
function renderItem({ item }) {
return (<Text>{this.getItemName(item)}</Text>);
}
// Data isn't redeclared each ender but [] is
// Extradata has a exponential complexity (will iterate the entire array for each render, could render once or several times in a second)
// Outcome will be that any new render on this component will cause the entire FlatList to render again, including children components, even if the data hasn't changed.
return (<FlatList
renderItem={renderItem}
data={data ?? []}
extraData={dataArray.filter(id => !!id)}
/>);
}
}
```
In the previous example there are two issues, a function and a object that will be dynamically redeclared each time the component renders, which will cause FlatList to keep re-rendering even when the input data hasn't changed.

@@ -76,5 +111,43 @@

// Will only render again if data changes
return (<FlatList renderItem={renderItem} data={data ?? EMPTY_ARRAY} />);
}
```
## **Correct** (class component)
```JavaScript
// Static therefore is only declared once
const EMPTY_ARRAY = [];
class Component() {
constructor(props) {
super(props);
this.state = {
data: undefined,
propDrivenData: props.dataArray.filter(id => !!id),
};
}
// Properly regenerate state driven data only when props change instead of during each render
static getDerivedStateFromProps(props) {
if (props.propDrivenData !== this.props.propDrivenData) {
return {
propDrivenData: props.dataArray.filter(id => !!id),
};
}
return null;
}
<FlatList renderItem={renderItem} data={data ?? EMPTY_ARRAY} />
// Will be declared only once.
getItemName({item}) {
const { data } = this.state;
const dataLength = data ? data.length : 0;
return (<Text>{item.name} {dataLength}</Text>);
}
render() {
const { data } = this.state;
// Will only cause a new render if data changes
return (<FlatList renderItem={this.renderItem} data={data ?? EMPTY_ARRAY} />);
}
}

@@ -92,6 +165,6 @@ ```

const renderItem = useCallback(({ item }) => {
return <Text>{isEditing ? 'item.name' : 'Editing'}</Text>;
return (<Text>{isEditing ? 'item.name' : 'Editing'}</Text>);
}, [isEditing]);
<FlatList renderItem={renderItem} data={data ?? EMPTY_ARRAY} />
return (<FlatList renderItem={renderItem} data={data ?? EMPTY_ARRAY} />);
}

@@ -107,4 +180,3 @@ ```

export default function Component() {
<Text>This is a component</Text>
return (<Text>This is a component</Text>);
}

@@ -116,4 +188,3 @@ ```

export default memo(function Component() {
<Text>This is a component</Text>
return (<Text>This is a component</Text>);
});

@@ -134,7 +205,7 @@ ```

<View>
return (<View>
<>
<OtherComponent />
</>
</View>
</View>);
}

@@ -146,8 +217,8 @@ ```

function Component() {
const children = useMemo(() => (<OtherComponent />), []);
<View>
return (<View>
{children}
</View>
</View>);
}
```
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