eslint-plugin-react-hooks-extra 1.8.0 → 1.8.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +95 -9
- package/dist/index.mjs +96 -10
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ export default [
|
|
|
41
41
|
|
|
42
42
|
## Rules
|
|
43
43
|
|
|
44
|
-
| Rule | Description | 💼 | 💭 |
|
|
44
|
+
| Rule | Description | 💼 | 💭 | 🪧 |
|
|
45
45
|
| :----------------------------------------- | :------------------------------------------------------------------------------ | :-: | :-: | :-: |
|
|
46
46
|
| `ensure-custom-hooks-using-other-hooks` | Warns when custom Hooks that don't use other Hooks. | ✔️ | | |
|
|
47
47
|
| `ensure-use-callback-has-non-empty-deps` | Warns when `useCallback` is called with empty dependencies array. | 🧐 | | |
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
|
30
30
|
|
|
31
31
|
// package.json
|
|
32
32
|
var name = "eslint-plugin-react-hooks-extra";
|
|
33
|
-
var version = "1.8.
|
|
33
|
+
var version = "1.8.1-next.1";
|
|
34
34
|
var createRule = shared.createRuleForPlugin("hooks-extra");
|
|
35
35
|
function isFromUseStateCall(context, useStateAlias) {
|
|
36
36
|
return (topLevelId) => {
|
|
@@ -507,6 +507,8 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
507
507
|
const effectFunctionIdentifiers = [];
|
|
508
508
|
const indirectFunctionCalls = [];
|
|
509
509
|
const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
510
|
+
const indirectSetStateCallsAsEFs = /* @__PURE__ */ new Map();
|
|
511
|
+
const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
|
|
510
512
|
const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
|
|
511
513
|
const onEffectFunctionEnter = (node) => {
|
|
512
514
|
tools.MutRef.set(effectFunctionRef, node);
|
|
@@ -533,9 +535,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
533
535
|
$(getCallKind(node, context, [useStateAlias, useEffectAlias])).with("setState", () => {
|
|
534
536
|
if (!parentFn) return;
|
|
535
537
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
536
|
-
const
|
|
537
|
-
if (tools.O.isSome(
|
|
538
|
-
const vd =
|
|
538
|
+
const maybeVd = ast.traverseUpGuard(node, isVariableDeclaratorFromHookCall);
|
|
539
|
+
if (tools.O.isSome(maybeVd)) {
|
|
540
|
+
const vd = maybeVd.value;
|
|
539
541
|
const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
|
|
540
542
|
indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
|
|
541
543
|
return;
|
|
@@ -558,6 +560,38 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
558
560
|
indirectFunctionCalls.push(node);
|
|
559
561
|
}).otherwise(tools.F.constVoid);
|
|
560
562
|
},
|
|
563
|
+
Identifier(node) {
|
|
564
|
+
if (!node.parent) return;
|
|
565
|
+
if (!isFromUseStateCall(context, useStateAlias)(node)) return;
|
|
566
|
+
switch (node.parent.type) {
|
|
567
|
+
case ast.NodeType.CallExpression: {
|
|
568
|
+
const [firstArg] = node.parent.arguments;
|
|
569
|
+
if (node !== firstArg) break;
|
|
570
|
+
if (core.isReactHookCallWithNameAlias("useCallback", context, useStateAlias)(node.parent)) {
|
|
571
|
+
const maybeVd = ast.traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
|
|
572
|
+
if (tools.O.isNone(maybeVd)) break;
|
|
573
|
+
const vd = maybeVd.value;
|
|
574
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
575
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
576
|
+
}
|
|
577
|
+
if (core.isReactHookCallWithNameAlias("useEffect", context, useEffectAlias)(node.parent)) {
|
|
578
|
+
const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
|
|
579
|
+
indirectSetStateCallsAsEFs.set(node.parent, [...calls, node]);
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
case ast.NodeType.ArrowFunctionExpression: {
|
|
584
|
+
const parent = node.parent.parent;
|
|
585
|
+
if (parent?.type !== ast.NodeType.CallExpression) break;
|
|
586
|
+
if (!core.isReactHookCallWithNameAlias("useMemo", context, useStateAlias)(parent)) break;
|
|
587
|
+
const maybeVd = ast.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
588
|
+
if (tools.O.isNone(maybeVd)) break;
|
|
589
|
+
const vd = maybeVd.value;
|
|
590
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
591
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
},
|
|
561
595
|
"Program:exit"() {
|
|
562
596
|
const getSetStateCalls = (id, initialScope) => {
|
|
563
597
|
const node = tools.O.flatMap(_var.findVariable(id, initialScope), _var.getVariableNode(0)).pipe(tools.O.getOrNull);
|
|
@@ -567,10 +601,19 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
567
601
|
case ast.NodeType.ArrowFunctionExpression:
|
|
568
602
|
return indirectSetStateCalls.get(node) ?? [];
|
|
569
603
|
case ast.NodeType.CallExpression:
|
|
570
|
-
return indirectSetStateCallsInHooks.get(node) ?? [];
|
|
604
|
+
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
571
605
|
}
|
|
572
606
|
return [];
|
|
573
607
|
};
|
|
608
|
+
for (const [_2, calls] of indirectSetStateCallsAsEFs) {
|
|
609
|
+
for (const call of calls) {
|
|
610
|
+
context.report({
|
|
611
|
+
data: { name: call.name },
|
|
612
|
+
messageId: "NO_DIRECT_SET_STATE_IN_USE_EFFECT",
|
|
613
|
+
node: call
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
574
617
|
for (const { callee } of indirectFunctionCalls) {
|
|
575
618
|
if (!("name" in callee)) continue;
|
|
576
619
|
const { name: name2 } = callee;
|
|
@@ -629,6 +672,8 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
629
672
|
const effectFunctionIdentifiers = [];
|
|
630
673
|
const indirectFunctionCalls = [];
|
|
631
674
|
const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
675
|
+
const indirectSetStateCallsAsEFs = /* @__PURE__ */ new Map();
|
|
676
|
+
const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
|
|
632
677
|
const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
|
|
633
678
|
const onEffectFunctionEnter = (node) => {
|
|
634
679
|
tools.MutRef.set(effectFunctionRef, node);
|
|
@@ -655,9 +700,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
655
700
|
$(getCallKind2(node, context, [useStateAlias, useLayoutEffectAlias])).with("setState", () => {
|
|
656
701
|
if (!parentFn) return;
|
|
657
702
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
658
|
-
const
|
|
659
|
-
if (tools.O.isSome(
|
|
660
|
-
const vd =
|
|
703
|
+
const maybeVd = ast.traverseUpGuard(node, isVariableDeclaratorFromHookCall);
|
|
704
|
+
if (tools.O.isSome(maybeVd)) {
|
|
705
|
+
const vd = maybeVd.value;
|
|
661
706
|
const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
|
|
662
707
|
indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
|
|
663
708
|
return;
|
|
@@ -680,6 +725,38 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
680
725
|
indirectFunctionCalls.push(node);
|
|
681
726
|
}).otherwise(tools.F.constVoid);
|
|
682
727
|
},
|
|
728
|
+
Identifier(node) {
|
|
729
|
+
if (!node.parent) return;
|
|
730
|
+
if (!isFromUseStateCall(context, useStateAlias)(node)) return;
|
|
731
|
+
switch (node.parent.type) {
|
|
732
|
+
case ast.NodeType.CallExpression: {
|
|
733
|
+
const [firstArg] = node.parent.arguments;
|
|
734
|
+
if (node !== firstArg) break;
|
|
735
|
+
if (core.isReactHookCallWithNameAlias("useCallback", context, useStateAlias)(node.parent)) {
|
|
736
|
+
const maybeVd = ast.traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
|
|
737
|
+
if (tools.O.isNone(maybeVd)) break;
|
|
738
|
+
const vd = maybeVd.value;
|
|
739
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
740
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
741
|
+
}
|
|
742
|
+
if (core.isReactHookCallWithNameAlias("useLayoutEffect", context, useLayoutEffectAlias)(node.parent)) {
|
|
743
|
+
const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
|
|
744
|
+
indirectSetStateCallsAsEFs.set(node.parent, [...calls, node]);
|
|
745
|
+
}
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
case ast.NodeType.ArrowFunctionExpression: {
|
|
749
|
+
const parent = node.parent.parent;
|
|
750
|
+
if (parent?.type !== ast.NodeType.CallExpression) break;
|
|
751
|
+
if (!core.isReactHookCallWithNameAlias("useMemo", context, useStateAlias)(parent)) break;
|
|
752
|
+
const maybeVd = ast.traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
753
|
+
if (tools.O.isNone(maybeVd)) break;
|
|
754
|
+
const vd = maybeVd.value;
|
|
755
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
756
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
},
|
|
683
760
|
"Program:exit"() {
|
|
684
761
|
const getSetStateCalls = (id, initialScope) => {
|
|
685
762
|
const node = tools.O.flatMap(_var.findVariable(id, initialScope), _var.getVariableNode(0)).pipe(tools.O.getOrNull);
|
|
@@ -689,10 +766,19 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
689
766
|
case ast.NodeType.ArrowFunctionExpression:
|
|
690
767
|
return indirectSetStateCalls.get(node) ?? [];
|
|
691
768
|
case ast.NodeType.CallExpression:
|
|
692
|
-
return indirectSetStateCallsInHooks.get(node) ?? [];
|
|
769
|
+
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
693
770
|
}
|
|
694
771
|
return [];
|
|
695
772
|
};
|
|
773
|
+
for (const [_2, calls] of indirectSetStateCallsAsEFs) {
|
|
774
|
+
for (const call of calls) {
|
|
775
|
+
context.report({
|
|
776
|
+
data: { name: call.name },
|
|
777
|
+
messageId: "NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT",
|
|
778
|
+
node: call
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}
|
|
696
782
|
for (const { callee } of indirectFunctionCalls) {
|
|
697
783
|
if (!("name" in callee)) continue;
|
|
698
784
|
const { name: name2 } = callee;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall, isReactHookName
|
|
1
|
+
import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isReactHookCallWithNameAlias, isUseStateCall, isReactHookName } from '@eslint-react/core';
|
|
2
2
|
import { createRuleForPlugin, decodeSettings } from '@eslint-react/shared';
|
|
3
3
|
import { isFunction, NodeType, is, traverseUpGuard, getNestedIdentifiers, getNestedCallExpressions, isIIFE } from '@eslint-react/ast';
|
|
4
4
|
import { F, O, MutRef } from '@eslint-react/tools';
|
|
@@ -8,7 +8,7 @@ import * as R from 'remeda';
|
|
|
8
8
|
|
|
9
9
|
// package.json
|
|
10
10
|
var name = "eslint-plugin-react-hooks-extra";
|
|
11
|
-
var version = "1.8.
|
|
11
|
+
var version = "1.8.1-next.1";
|
|
12
12
|
var createRule = createRuleForPlugin("hooks-extra");
|
|
13
13
|
function isFromUseStateCall(context, useStateAlias) {
|
|
14
14
|
return (topLevelId) => {
|
|
@@ -485,6 +485,8 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
485
485
|
const effectFunctionIdentifiers = [];
|
|
486
486
|
const indirectFunctionCalls = [];
|
|
487
487
|
const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
488
|
+
const indirectSetStateCallsAsEFs = /* @__PURE__ */ new Map();
|
|
489
|
+
const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
|
|
488
490
|
const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
|
|
489
491
|
const onEffectFunctionEnter = (node) => {
|
|
490
492
|
MutRef.set(effectFunctionRef, node);
|
|
@@ -511,9 +513,9 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
511
513
|
$(getCallKind(node, context, [useStateAlias, useEffectAlias])).with("setState", () => {
|
|
512
514
|
if (!parentFn) return;
|
|
513
515
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
514
|
-
const
|
|
515
|
-
if (O.isSome(
|
|
516
|
-
const vd =
|
|
516
|
+
const maybeVd = traverseUpGuard(node, isVariableDeclaratorFromHookCall);
|
|
517
|
+
if (O.isSome(maybeVd)) {
|
|
518
|
+
const vd = maybeVd.value;
|
|
517
519
|
const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
|
|
518
520
|
indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
|
|
519
521
|
return;
|
|
@@ -536,6 +538,38 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
536
538
|
indirectFunctionCalls.push(node);
|
|
537
539
|
}).otherwise(F.constVoid);
|
|
538
540
|
},
|
|
541
|
+
Identifier(node) {
|
|
542
|
+
if (!node.parent) return;
|
|
543
|
+
if (!isFromUseStateCall(context, useStateAlias)(node)) return;
|
|
544
|
+
switch (node.parent.type) {
|
|
545
|
+
case NodeType.CallExpression: {
|
|
546
|
+
const [firstArg] = node.parent.arguments;
|
|
547
|
+
if (node !== firstArg) break;
|
|
548
|
+
if (isReactHookCallWithNameAlias("useCallback", context, useStateAlias)(node.parent)) {
|
|
549
|
+
const maybeVd = traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
|
|
550
|
+
if (O.isNone(maybeVd)) break;
|
|
551
|
+
const vd = maybeVd.value;
|
|
552
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
553
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
554
|
+
}
|
|
555
|
+
if (isReactHookCallWithNameAlias("useEffect", context, useEffectAlias)(node.parent)) {
|
|
556
|
+
const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
|
|
557
|
+
indirectSetStateCallsAsEFs.set(node.parent, [...calls, node]);
|
|
558
|
+
}
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
case NodeType.ArrowFunctionExpression: {
|
|
562
|
+
const parent = node.parent.parent;
|
|
563
|
+
if (parent?.type !== NodeType.CallExpression) break;
|
|
564
|
+
if (!isReactHookCallWithNameAlias("useMemo", context, useStateAlias)(parent)) break;
|
|
565
|
+
const maybeVd = traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
566
|
+
if (O.isNone(maybeVd)) break;
|
|
567
|
+
const vd = maybeVd.value;
|
|
568
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
569
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
},
|
|
539
573
|
"Program:exit"() {
|
|
540
574
|
const getSetStateCalls = (id, initialScope) => {
|
|
541
575
|
const node = O.flatMap(findVariable(id, initialScope), getVariableNode(0)).pipe(O.getOrNull);
|
|
@@ -545,10 +579,19 @@ var no_direct_set_state_in_use_effect_default = createRule({
|
|
|
545
579
|
case NodeType.ArrowFunctionExpression:
|
|
546
580
|
return indirectSetStateCalls.get(node) ?? [];
|
|
547
581
|
case NodeType.CallExpression:
|
|
548
|
-
return indirectSetStateCallsInHooks.get(node) ?? [];
|
|
582
|
+
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
549
583
|
}
|
|
550
584
|
return [];
|
|
551
585
|
};
|
|
586
|
+
for (const [_2, calls] of indirectSetStateCallsAsEFs) {
|
|
587
|
+
for (const call of calls) {
|
|
588
|
+
context.report({
|
|
589
|
+
data: { name: call.name },
|
|
590
|
+
messageId: "NO_DIRECT_SET_STATE_IN_USE_EFFECT",
|
|
591
|
+
node: call
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
552
595
|
for (const { callee } of indirectFunctionCalls) {
|
|
553
596
|
if (!("name" in callee)) continue;
|
|
554
597
|
const { name: name2 } = callee;
|
|
@@ -607,6 +650,8 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
607
650
|
const effectFunctionIdentifiers = [];
|
|
608
651
|
const indirectFunctionCalls = [];
|
|
609
652
|
const indirectSetStateCalls = /* @__PURE__ */ new WeakMap();
|
|
653
|
+
const indirectSetStateCallsAsEFs = /* @__PURE__ */ new Map();
|
|
654
|
+
const indirectSetStateCallsAsArgs = /* @__PURE__ */ new WeakMap();
|
|
610
655
|
const indirectSetStateCallsInHooks = /* @__PURE__ */ new WeakMap();
|
|
611
656
|
const onEffectFunctionEnter = (node) => {
|
|
612
657
|
MutRef.set(effectFunctionRef, node);
|
|
@@ -633,9 +678,9 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
633
678
|
$(getCallKind2(node, context, [useStateAlias, useLayoutEffectAlias])).with("setState", () => {
|
|
634
679
|
if (!parentFn) return;
|
|
635
680
|
if (parentFn !== effectFn && parentFnKind !== "immediate") {
|
|
636
|
-
const
|
|
637
|
-
if (O.isSome(
|
|
638
|
-
const vd =
|
|
681
|
+
const maybeVd = traverseUpGuard(node, isVariableDeclaratorFromHookCall);
|
|
682
|
+
if (O.isSome(maybeVd)) {
|
|
683
|
+
const vd = maybeVd.value;
|
|
639
684
|
const calls2 = indirectSetStateCallsInHooks.get(vd.init) ?? [];
|
|
640
685
|
indirectSetStateCallsInHooks.set(vd.init, [...calls2, node]);
|
|
641
686
|
return;
|
|
@@ -658,6 +703,38 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
658
703
|
indirectFunctionCalls.push(node);
|
|
659
704
|
}).otherwise(F.constVoid);
|
|
660
705
|
},
|
|
706
|
+
Identifier(node) {
|
|
707
|
+
if (!node.parent) return;
|
|
708
|
+
if (!isFromUseStateCall(context, useStateAlias)(node)) return;
|
|
709
|
+
switch (node.parent.type) {
|
|
710
|
+
case NodeType.CallExpression: {
|
|
711
|
+
const [firstArg] = node.parent.arguments;
|
|
712
|
+
if (node !== firstArg) break;
|
|
713
|
+
if (isReactHookCallWithNameAlias("useCallback", context, useStateAlias)(node.parent)) {
|
|
714
|
+
const maybeVd = traverseUpGuard(node.parent, isVariableDeclaratorFromHookCall);
|
|
715
|
+
if (O.isNone(maybeVd)) break;
|
|
716
|
+
const vd = maybeVd.value;
|
|
717
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
718
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
719
|
+
}
|
|
720
|
+
if (isReactHookCallWithNameAlias("useLayoutEffect", context, useLayoutEffectAlias)(node.parent)) {
|
|
721
|
+
const calls = indirectSetStateCallsAsArgs.get(node.parent) ?? [];
|
|
722
|
+
indirectSetStateCallsAsEFs.set(node.parent, [...calls, node]);
|
|
723
|
+
}
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
case NodeType.ArrowFunctionExpression: {
|
|
727
|
+
const parent = node.parent.parent;
|
|
728
|
+
if (parent?.type !== NodeType.CallExpression) break;
|
|
729
|
+
if (!isReactHookCallWithNameAlias("useMemo", context, useStateAlias)(parent)) break;
|
|
730
|
+
const maybeVd = traverseUpGuard(parent, isVariableDeclaratorFromHookCall);
|
|
731
|
+
if (O.isNone(maybeVd)) break;
|
|
732
|
+
const vd = maybeVd.value;
|
|
733
|
+
const calls = indirectSetStateCallsAsArgs.get(vd.init) ?? [];
|
|
734
|
+
indirectSetStateCallsAsArgs.set(vd.init, [...calls, node]);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
},
|
|
661
738
|
"Program:exit"() {
|
|
662
739
|
const getSetStateCalls = (id, initialScope) => {
|
|
663
740
|
const node = O.flatMap(findVariable(id, initialScope), getVariableNode(0)).pipe(O.getOrNull);
|
|
@@ -667,10 +744,19 @@ var no_direct_set_state_in_use_layout_effect_default = createRule({
|
|
|
667
744
|
case NodeType.ArrowFunctionExpression:
|
|
668
745
|
return indirectSetStateCalls.get(node) ?? [];
|
|
669
746
|
case NodeType.CallExpression:
|
|
670
|
-
return indirectSetStateCallsInHooks.get(node) ?? [];
|
|
747
|
+
return indirectSetStateCallsInHooks.get(node) ?? indirectSetStateCallsAsArgs.get(node) ?? [];
|
|
671
748
|
}
|
|
672
749
|
return [];
|
|
673
750
|
};
|
|
751
|
+
for (const [_2, calls] of indirectSetStateCallsAsEFs) {
|
|
752
|
+
for (const call of calls) {
|
|
753
|
+
context.report({
|
|
754
|
+
data: { name: call.name },
|
|
755
|
+
messageId: "NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT",
|
|
756
|
+
node: call
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
}
|
|
674
760
|
for (const { callee } of indirectFunctionCalls) {
|
|
675
761
|
if (!("name" in callee)) continue;
|
|
676
762
|
const { name: name2 } = callee;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-hooks-extra",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1-next.1",
|
|
4
4
|
"description": "ESLint React's ESLint plugin for React Hooks related rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"@typescript-eslint/types": "^8.0.0",
|
|
47
47
|
"@typescript-eslint/utils": "^8.0.0",
|
|
48
48
|
"remeda": "^2.6.0",
|
|
49
|
-
"@eslint-react/ast": "1.8.
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/core": "1.8.
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/tools": "1.8.
|
|
54
|
-
"@eslint-react/types": "1.8.
|
|
55
|
-
"@eslint-react/var": "1.8.
|
|
49
|
+
"@eslint-react/ast": "1.8.1-next.1",
|
|
50
|
+
"@eslint-react/shared": "1.8.1-next.1",
|
|
51
|
+
"@eslint-react/core": "1.8.1-next.1",
|
|
52
|
+
"@eslint-react/jsx": "1.8.1-next.1",
|
|
53
|
+
"@eslint-react/tools": "1.8.1-next.1",
|
|
54
|
+
"@eslint-react/types": "1.8.1-next.1",
|
|
55
|
+
"@eslint-react/var": "1.8.1-next.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/react": "^18.3.3",
|