Skip to content

Commit de475cc

Browse files
committed
Analyze IIFEs
Closes #16
1 parent 01c62b9 commit de475cc

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

src/rule.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { messageIds, messages } from "./messages.js";
2-
import { getCallExpr, getDownstreamRefs } from "./util/ast.js";
2+
import { getCallExpr, getDownstreamRefs, findIIFE } from "./util/ast.js";
33
import {
4-
isFnRef,
54
findPropUsedToResetAllState,
65
isUseEffect,
76
getUseStateNode,
87
getEffectFnRefs,
98
getDependenciesRefs,
109
isStateSetter,
1110
isPropCallback,
12-
getEffectFn,
1311
isDirectCall,
1412
getUpstreamReactVariables,
1513
isState,
@@ -75,7 +73,11 @@ export const rule = {
7573
// Don't analyze HOC prop callbacks -- we don't have control over them to lift state or logic
7674
!isHOCProp(ref.resolved)),
7775
)
78-
.filter((ref) => isDirectCall(ref.identifier))
76+
.filter(
77+
(ref) =>
78+
isDirectCall(ref.identifier) ||
79+
isDirectCall(findIIFE(ref.identifier)),
80+
)
7981
.forEach((ref) => {
8082
const callExpr = getCallExpr(ref);
8183

src/util/ast.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,18 @@ export const getCallExpr = (ref, current = ref.identifier.parent) => {
9494

9595
return undefined;
9696
};
97+
98+
export const findIIFE = (node) => {
99+
if (!node) {
100+
return undefined;
101+
} else if (
102+
node.type === "CallExpression" &&
103+
(node.callee.type === "ArrowFunctionExpression" ||
104+
node.callee.type === "FunctionExpression")
105+
) {
106+
return node;
107+
} else {
108+
return findIIFE(node.parent);
109+
}
110+
};
111+

test/syntax.test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ new MyRuleTester().run("/syntax", {
153153
};
154154
`,
155155
},
156+
{
157+
name: "Internal IIFE inside callback",
158+
code: js`
159+
import { useEffect, useState } from 'react';
160+
161+
export const MyComponent = () => {
162+
const [state, setState] = useState();
163+
164+
useEffect(() => {
165+
window.addEventListener('load', () => {
166+
(async () => {
167+
setState('Loaded');
168+
})();
169+
});
170+
}, []);
171+
};
172+
`,
173+
},
156174
],
157175
invalid: [
158176
{
@@ -493,7 +511,6 @@ new MyRuleTester().run("/syntax", {
493511
{
494512
// https://github.com/NickvanDyke/eslint-plugin-react-you-might-not-need-an-effect/issues/16
495513
name: "Internal IIFE",
496-
todo: true, // TODO: `isDirectCall` returns false for IIFEs, so we don't follow `iife`. Otherwise it works.
497514
code: js`
498515
import { useEffect, useState } from 'react';
499516
@@ -515,7 +532,7 @@ new MyRuleTester().run("/syntax", {
515532
`,
516533
errors: [
517534
{
518-
messageId: messageIds.avoidChainingState,
535+
messageId: messageIds.avoidInitializingState,
519536
},
520537
],
521538
},

0 commit comments

Comments
 (0)