eslint-plugin-react-hooks-extra 1.5.25 → 1.5.26-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 CHANGED
@@ -30,7 +30,8 @@ export default [
30
30
  "react-hooks-extra": reactHooksExtra,
31
31
  rules: {
32
32
  // react-hooks-extra recommended rules
33
- "react-hooks-extra/ensure-custom-hooks-using-other-hooks": "warn",
33
+ "react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
34
+ "react-hooks-extra/no-direct-set-state-in-use-layout-effect": "warn",
34
35
  "react-hooks-extra/prefer-use-state-lazy-initialization": "warn",
35
36
  }
36
37
  ],
@@ -40,9 +41,11 @@ export default [
40
41
 
41
42
  ## Rules
42
43
 
43
- | Rule | Description | 💼 | 💭 | ❌ |
44
- | :--------------------------------------- | :---------------------------------------------------------------- | :-: | :-: | :-: |
45
- | `ensure-custom-hooks-using-other-hooks` | Warns when custom Hooks that don't use other Hooks. | ✔️ | | |
46
- | `ensure-use-callback-has-non-empty-deps` | Warns when `useCallback` is called with empty dependencies array. | 🧐 | | |
47
- | `ensure-use-memo-has-non-empty-deps` | Warns when `useMemo` is called with empty dependencies array. | 🧐 | | |
48
- | `prefer-use-state-lazy-initialization` | Warns function calls made inside `useState` calls. | 🚀 | | |
44
+ | Rule | Description | 💼 | 💭 | ❌ |
45
+ | :----------------------------------------- | :------------------------------------------------------------------------------ | :-: | :-: | :-: |
46
+ | `ensure-custom-hooks-using-other-hooks` | Warns when custom Hooks that don't use other Hooks. | ✔️ | | |
47
+ | `ensure-use-callback-has-non-empty-deps` | Warns when `useCallback` is called with empty dependencies array. | 🧐 | | |
48
+ | `ensure-use-memo-has-non-empty-deps` | Warns when `useMemo` is called with empty dependencies array. | 🧐 | | |
49
+ | `no-direct-set-state-in-use-effect` | Disallow direct calls to the `set` function of `useState` in `useEffect`. | ✔️ | | |
50
+ | `no-direct-set-state-in-use-layout-effect` | Disallow direct calls to the `set` function of `useState` in `useLayoutEffect`. | ✔️ | | |
51
+ | `prefer-use-state-lazy-initialization` | Warns function calls made inside `useState` calls. | 🚀 | | |
package/dist/index.d.mts CHANGED
@@ -8,6 +8,8 @@ declare const rules: {
8
8
  readonly "ensure-custom-hooks-using-other-hooks": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
9
9
  readonly "ensure-use-callback-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
10
10
  readonly "ensure-use-memo-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
11
+ readonly "no-direct-set-state-in-use-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"NO_DIRECT_SET_STATE_IN_USE_EFFECT", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
12
+ readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
11
13
  readonly "prefer-use-state-lazy-initialization": _typescript_eslint_utils_ts_eslint.RuleModule<"PREFER_USE_STATE_LAZY_INITIALIZATION", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
12
14
  };
13
15
 
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ declare const rules: {
8
8
  readonly "ensure-custom-hooks-using-other-hooks": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_CUSTOM_HOOKS_USING_OTHER_HOOKS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
9
9
  readonly "ensure-use-callback-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_USE_CALLBACK_HAS_NON_EMPTY_DEPS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
10
10
  readonly "ensure-use-memo-has-non-empty-deps": _typescript_eslint_utils_ts_eslint.RuleModule<"ENSURE_USE_MEMO_HAS_NON_EMPTY_DEPS", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
11
+ readonly "no-direct-set-state-in-use-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"NO_DIRECT_SET_STATE_IN_USE_EFFECT", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
12
+ readonly "no-direct-set-state-in-use-layout-effect": _typescript_eslint_utils_ts_eslint.RuleModule<"NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
11
13
  readonly "prefer-use-state-lazy-initialization": _typescript_eslint_utils_ts_eslint.RuleModule<"PREFER_USE_STATE_LAZY_INITIALIZATION", [], _typescript_eslint_utils_ts_eslint.RuleListener>;
12
14
  };
13
15
 
package/dist/index.js CHANGED
@@ -5,10 +5,11 @@ var shared = require('@eslint-react/shared');
5
5
  var ast = require('@eslint-react/ast');
6
6
  var tools = require('@eslint-react/tools');
7
7
  var _var = require('@eslint-react/var');
8
+ var astUtils = require('@typescript-eslint/utils/ast-utils');
8
9
 
9
10
  // package.json
10
11
  var name = "eslint-plugin-react-hooks-extra";
11
- var version = "1.5.25";
12
+ var version = "1.5.26-next.1";
12
13
  var createRule = shared.createRuleForPlugin("hooks-extra");
13
14
 
14
15
  // src/rules/ensure-custom-hooks-using-other-hooks.ts
@@ -316,7 +317,163 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
316
317
  },
317
318
  defaultOptions: []
318
319
  });
319
- var RULE_NAME4 = "prefer-use-state-lazy-initialization";
320
+ var RULE_NAME4 = "no-direct-set-state-in-use-effect";
321
+ var no_direct_set_state_in_use_effect_default = createRule({
322
+ meta: {
323
+ type: "problem",
324
+ docs: {
325
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useEffect'"
326
+ },
327
+ messages: {
328
+ NO_DIRECT_SET_STATE_IN_USE_EFFECT: "Do not call the 'set' function of 'useState' directly in 'useEffect'."
329
+ },
330
+ schema: []
331
+ },
332
+ name: RULE_NAME4,
333
+ create(context) {
334
+ const settings = shared.getESLintReactSettings(context.settings);
335
+ const { useEffect: useEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
336
+ function isUseEffectCallWithAlias(node, context2) {
337
+ return core.isUseEffectCall(node, context2) || useEffectAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
338
+ }
339
+ function isUseStateCallWithAlias(node, context2) {
340
+ return core.isUseStateCall(node, context2) || useStateAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
341
+ }
342
+ function isEffectFunction(node) {
343
+ return node.parent?.type === ast.NodeType.CallExpression && isUseEffectCallWithAlias(node.parent, context);
344
+ }
345
+ return {
346
+ CallExpression(node) {
347
+ const effectFunction = ast.traverseUp(node, isEffectFunction);
348
+ if (tools.O.isNone(effectFunction)) return;
349
+ const scope = context.sourceCode.getScope(node);
350
+ if (scope.block !== effectFunction.value) return;
351
+ const name2 = $(node.callee).with({ type: ast.NodeType.Identifier }, (n2) => tools.O.some(n2.name)).with({ type: ast.NodeType.MemberExpression }, (n2) => {
352
+ if (!("name" in n2.object)) return tools.O.none();
353
+ const initialScope = context.sourceCode.getScope(n2);
354
+ const property = astUtils.getStaticValue(n2.property, initialScope);
355
+ if (property?.value === 1) return tools.O.fromNullable(n2.object.name);
356
+ return tools.O.none();
357
+ }).with({ type: ast.NodeType.CallExpression }, (n2) => {
358
+ if (!ast.is(ast.NodeType.MemberExpression)(n2.callee)) return tools.O.none();
359
+ if (!("name" in n2.callee.object)) return tools.O.none();
360
+ const isAt = $(n2.callee).with(
361
+ {
362
+ type: ast.NodeType.MemberExpression,
363
+ property: {
364
+ type: ast.NodeType.Identifier,
365
+ name: "at"
366
+ }
367
+ },
368
+ tools.F.constTrue
369
+ ).otherwise(tools.F.constFalse);
370
+ if (!isAt) return tools.O.none();
371
+ const [index] = n2.arguments;
372
+ if (!index) return tools.O.none();
373
+ const initialScope = context.sourceCode.getScope(n2);
374
+ const value = astUtils.getStaticValue(index, initialScope);
375
+ if (value?.value === 1) return tools.O.fromNullable(n2.callee.object.name);
376
+ return tools.O.none();
377
+ }).otherwise(tools.O.none);
378
+ tools.F.pipe(
379
+ name2,
380
+ tools.O.flatMap(_var.findVariable(scope)),
381
+ tools.O.flatMap(_var.getVariableInit(0)),
382
+ tools.O.filter(ast.is(ast.NodeType.CallExpression)),
383
+ tools.O.filter((name3) => isUseStateCallWithAlias(name3, context)),
384
+ tools.O.map((name3) => ({
385
+ data: {
386
+ setState: name3
387
+ },
388
+ messageId: "NO_DIRECT_SET_STATE_IN_USE_EFFECT",
389
+ node
390
+ })),
391
+ tools.O.map(context.report)
392
+ );
393
+ }
394
+ };
395
+ },
396
+ defaultOptions: []
397
+ });
398
+ var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
399
+ var no_direct_set_state_in_use_layout_effect_default = createRule({
400
+ meta: {
401
+ type: "problem",
402
+ docs: {
403
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useLayoutEffect'"
404
+ },
405
+ messages: {
406
+ NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT: "Do not call the 'set' function of 'useState' directly in 'useLayoutEffect'."
407
+ },
408
+ schema: []
409
+ },
410
+ name: RULE_NAME5,
411
+ create(context) {
412
+ const settings = shared.getESLintReactSettings(context.settings);
413
+ const { useLayoutEffect: useLayoutEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
414
+ function isUseLayoutEffectCallWithAlias(node, context2) {
415
+ return core.isUseLayoutEffectCall(node, context2) || useLayoutEffectAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
416
+ }
417
+ function isUseStateCallWithAlias(node, context2) {
418
+ return core.isUseStateCall(node, context2) || useStateAlias.some(tools.F.flip(core.isReactHookCallWithNameLoose)(node));
419
+ }
420
+ function isEffectFunction(node) {
421
+ return node.parent?.type === ast.NodeType.CallExpression && isUseLayoutEffectCallWithAlias(node.parent, context);
422
+ }
423
+ return {
424
+ CallExpression(node) {
425
+ const effectFunction = ast.traverseUp(node, isEffectFunction);
426
+ if (tools.O.isNone(effectFunction)) return;
427
+ const scope = context.sourceCode.getScope(node);
428
+ if (scope.block !== effectFunction.value) return;
429
+ const name2 = $(node.callee).with({ type: ast.NodeType.Identifier }, (n2) => tools.O.some(n2.name)).with({ type: ast.NodeType.MemberExpression }, (n2) => {
430
+ if (!("name" in n2.object)) return tools.O.none();
431
+ const initialScope = context.sourceCode.getScope(n2);
432
+ const property = astUtils.getStaticValue(n2.property, initialScope);
433
+ if (property?.value === 1) return tools.O.fromNullable(n2.object.name);
434
+ return tools.O.none();
435
+ }).with({ type: ast.NodeType.CallExpression }, (n2) => {
436
+ if (!ast.is(ast.NodeType.MemberExpression)(n2.callee)) return tools.O.none();
437
+ if (!("name" in n2.callee.object)) return tools.O.none();
438
+ const isAt = $(n2.callee).with(
439
+ {
440
+ type: ast.NodeType.MemberExpression,
441
+ property: {
442
+ type: ast.NodeType.Identifier,
443
+ name: "at"
444
+ }
445
+ },
446
+ tools.F.constTrue
447
+ ).otherwise(tools.F.constFalse);
448
+ if (!isAt) return tools.O.none();
449
+ const [index] = n2.arguments;
450
+ if (!index) return tools.O.none();
451
+ const initialScope = context.sourceCode.getScope(n2);
452
+ const value = astUtils.getStaticValue(index, initialScope);
453
+ if (value?.value === 1) return tools.O.fromNullable(n2.callee.object.name);
454
+ return tools.O.none();
455
+ }).otherwise(tools.O.none);
456
+ tools.F.pipe(
457
+ name2,
458
+ tools.O.flatMap(_var.findVariable(scope)),
459
+ tools.O.flatMap(_var.getVariableInit(0)),
460
+ tools.O.filter(ast.is(ast.NodeType.CallExpression)),
461
+ tools.O.filter((name3) => isUseStateCallWithAlias(name3, context)),
462
+ tools.O.map((name3) => ({
463
+ data: {
464
+ setState: name3
465
+ },
466
+ messageId: "NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT",
467
+ node
468
+ })),
469
+ tools.O.map(context.report)
470
+ );
471
+ }
472
+ };
473
+ },
474
+ defaultOptions: []
475
+ });
476
+ var RULE_NAME6 = "prefer-use-state-lazy-initialization";
320
477
  var ALLOW_LIST = ["Boolean", "String", "Number"];
321
478
  var prefer_use_state_lazy_initialization_default = createRule({
322
479
  meta: {
@@ -329,7 +486,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
329
486
  },
330
487
  schema: []
331
488
  },
332
- name: RULE_NAME4,
489
+ name: RULE_NAME6,
333
490
  create(context) {
334
491
  const alias = shared.getESLintReactSettings(context.settings).additionalHooks?.useState ?? [];
335
492
  return {
@@ -362,6 +519,8 @@ var rules = {
362
519
  "ensure-custom-hooks-using-other-hooks": ensure_custom_hooks_using_other_hooks_default,
363
520
  "ensure-use-callback-has-non-empty-deps": ensure_use_callback_has_non_empty_deps_default,
364
521
  "ensure-use-memo-has-non-empty-deps": ensure_use_memo_has_non_empty_deps_default,
522
+ "no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default,
523
+ "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default,
365
524
  "prefer-use-state-lazy-initialization": prefer_use_state_lazy_initialization_default
366
525
  };
367
526
 
package/dist/index.mjs CHANGED
@@ -1,12 +1,13 @@
1
- import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall } from '@eslint-react/core';
1
+ import { useHookCollector, isReactHookCall, isUseCallbackCall, isReactHookCallWithNameLoose, isUseMemoCall, isUseStateCall, isUseEffectCall, isUseLayoutEffectCall } from '@eslint-react/core';
2
2
  import { createRuleForPlugin, getESLintReactSettings } from '@eslint-react/shared';
3
- import { NodeType, is, getNestedCallExpressions } from '@eslint-react/ast';
3
+ import { NodeType, is, traverseUp, getNestedCallExpressions } from '@eslint-react/ast';
4
4
  import { F, O } from '@eslint-react/tools';
5
5
  import { findVariable, getVariableInit } from '@eslint-react/var';
6
+ import { getStaticValue } from '@typescript-eslint/utils/ast-utils';
6
7
 
7
8
  // package.json
8
9
  var name = "eslint-plugin-react-hooks-extra";
9
- var version = "1.5.25";
10
+ var version = "1.5.26-next.1";
10
11
  var createRule = createRuleForPlugin("hooks-extra");
11
12
 
12
13
  // src/rules/ensure-custom-hooks-using-other-hooks.ts
@@ -314,7 +315,163 @@ var ensure_use_memo_has_non_empty_deps_default = createRule({
314
315
  },
315
316
  defaultOptions: []
316
317
  });
317
- var RULE_NAME4 = "prefer-use-state-lazy-initialization";
318
+ var RULE_NAME4 = "no-direct-set-state-in-use-effect";
319
+ var no_direct_set_state_in_use_effect_default = createRule({
320
+ meta: {
321
+ type: "problem",
322
+ docs: {
323
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useEffect'"
324
+ },
325
+ messages: {
326
+ NO_DIRECT_SET_STATE_IN_USE_EFFECT: "Do not call the 'set' function of 'useState' directly in 'useEffect'."
327
+ },
328
+ schema: []
329
+ },
330
+ name: RULE_NAME4,
331
+ create(context) {
332
+ const settings = getESLintReactSettings(context.settings);
333
+ const { useEffect: useEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
334
+ function isUseEffectCallWithAlias(node, context2) {
335
+ return isUseEffectCall(node, context2) || useEffectAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
336
+ }
337
+ function isUseStateCallWithAlias(node, context2) {
338
+ return isUseStateCall(node, context2) || useStateAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
339
+ }
340
+ function isEffectFunction(node) {
341
+ return node.parent?.type === NodeType.CallExpression && isUseEffectCallWithAlias(node.parent, context);
342
+ }
343
+ return {
344
+ CallExpression(node) {
345
+ const effectFunction = traverseUp(node, isEffectFunction);
346
+ if (O.isNone(effectFunction)) return;
347
+ const scope = context.sourceCode.getScope(node);
348
+ if (scope.block !== effectFunction.value) return;
349
+ const name2 = $(node.callee).with({ type: NodeType.Identifier }, (n2) => O.some(n2.name)).with({ type: NodeType.MemberExpression }, (n2) => {
350
+ if (!("name" in n2.object)) return O.none();
351
+ const initialScope = context.sourceCode.getScope(n2);
352
+ const property = getStaticValue(n2.property, initialScope);
353
+ if (property?.value === 1) return O.fromNullable(n2.object.name);
354
+ return O.none();
355
+ }).with({ type: NodeType.CallExpression }, (n2) => {
356
+ if (!is(NodeType.MemberExpression)(n2.callee)) return O.none();
357
+ if (!("name" in n2.callee.object)) return O.none();
358
+ const isAt = $(n2.callee).with(
359
+ {
360
+ type: NodeType.MemberExpression,
361
+ property: {
362
+ type: NodeType.Identifier,
363
+ name: "at"
364
+ }
365
+ },
366
+ F.constTrue
367
+ ).otherwise(F.constFalse);
368
+ if (!isAt) return O.none();
369
+ const [index] = n2.arguments;
370
+ if (!index) return O.none();
371
+ const initialScope = context.sourceCode.getScope(n2);
372
+ const value = getStaticValue(index, initialScope);
373
+ if (value?.value === 1) return O.fromNullable(n2.callee.object.name);
374
+ return O.none();
375
+ }).otherwise(O.none);
376
+ F.pipe(
377
+ name2,
378
+ O.flatMap(findVariable(scope)),
379
+ O.flatMap(getVariableInit(0)),
380
+ O.filter(is(NodeType.CallExpression)),
381
+ O.filter((name3) => isUseStateCallWithAlias(name3, context)),
382
+ O.map((name3) => ({
383
+ data: {
384
+ setState: name3
385
+ },
386
+ messageId: "NO_DIRECT_SET_STATE_IN_USE_EFFECT",
387
+ node
388
+ })),
389
+ O.map(context.report)
390
+ );
391
+ }
392
+ };
393
+ },
394
+ defaultOptions: []
395
+ });
396
+ var RULE_NAME5 = "no-direct-set-state-in-use-layout-effect";
397
+ var no_direct_set_state_in_use_layout_effect_default = createRule({
398
+ meta: {
399
+ type: "problem",
400
+ docs: {
401
+ description: "disallow direct calls to the 'set' function of 'useState' in 'useLayoutEffect'"
402
+ },
403
+ messages: {
404
+ NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT: "Do not call the 'set' function of 'useState' directly in 'useLayoutEffect'."
405
+ },
406
+ schema: []
407
+ },
408
+ name: RULE_NAME5,
409
+ create(context) {
410
+ const settings = getESLintReactSettings(context.settings);
411
+ const { useLayoutEffect: useLayoutEffectAlias = [], useState: useStateAlias = [] } = settings.additionalHooks ?? {};
412
+ function isUseLayoutEffectCallWithAlias(node, context2) {
413
+ return isUseLayoutEffectCall(node, context2) || useLayoutEffectAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
414
+ }
415
+ function isUseStateCallWithAlias(node, context2) {
416
+ return isUseStateCall(node, context2) || useStateAlias.some(F.flip(isReactHookCallWithNameLoose)(node));
417
+ }
418
+ function isEffectFunction(node) {
419
+ return node.parent?.type === NodeType.CallExpression && isUseLayoutEffectCallWithAlias(node.parent, context);
420
+ }
421
+ return {
422
+ CallExpression(node) {
423
+ const effectFunction = traverseUp(node, isEffectFunction);
424
+ if (O.isNone(effectFunction)) return;
425
+ const scope = context.sourceCode.getScope(node);
426
+ if (scope.block !== effectFunction.value) return;
427
+ const name2 = $(node.callee).with({ type: NodeType.Identifier }, (n2) => O.some(n2.name)).with({ type: NodeType.MemberExpression }, (n2) => {
428
+ if (!("name" in n2.object)) return O.none();
429
+ const initialScope = context.sourceCode.getScope(n2);
430
+ const property = getStaticValue(n2.property, initialScope);
431
+ if (property?.value === 1) return O.fromNullable(n2.object.name);
432
+ return O.none();
433
+ }).with({ type: NodeType.CallExpression }, (n2) => {
434
+ if (!is(NodeType.MemberExpression)(n2.callee)) return O.none();
435
+ if (!("name" in n2.callee.object)) return O.none();
436
+ const isAt = $(n2.callee).with(
437
+ {
438
+ type: NodeType.MemberExpression,
439
+ property: {
440
+ type: NodeType.Identifier,
441
+ name: "at"
442
+ }
443
+ },
444
+ F.constTrue
445
+ ).otherwise(F.constFalse);
446
+ if (!isAt) return O.none();
447
+ const [index] = n2.arguments;
448
+ if (!index) return O.none();
449
+ const initialScope = context.sourceCode.getScope(n2);
450
+ const value = getStaticValue(index, initialScope);
451
+ if (value?.value === 1) return O.fromNullable(n2.callee.object.name);
452
+ return O.none();
453
+ }).otherwise(O.none);
454
+ F.pipe(
455
+ name2,
456
+ O.flatMap(findVariable(scope)),
457
+ O.flatMap(getVariableInit(0)),
458
+ O.filter(is(NodeType.CallExpression)),
459
+ O.filter((name3) => isUseStateCallWithAlias(name3, context)),
460
+ O.map((name3) => ({
461
+ data: {
462
+ setState: name3
463
+ },
464
+ messageId: "NO_DIRECT_SET_STATE_IN_USE_LAYOUT_EFFECT",
465
+ node
466
+ })),
467
+ O.map(context.report)
468
+ );
469
+ }
470
+ };
471
+ },
472
+ defaultOptions: []
473
+ });
474
+ var RULE_NAME6 = "prefer-use-state-lazy-initialization";
318
475
  var ALLOW_LIST = ["Boolean", "String", "Number"];
319
476
  var prefer_use_state_lazy_initialization_default = createRule({
320
477
  meta: {
@@ -327,7 +484,7 @@ var prefer_use_state_lazy_initialization_default = createRule({
327
484
  },
328
485
  schema: []
329
486
  },
330
- name: RULE_NAME4,
487
+ name: RULE_NAME6,
331
488
  create(context) {
332
489
  const alias = getESLintReactSettings(context.settings).additionalHooks?.useState ?? [];
333
490
  return {
@@ -360,6 +517,8 @@ var rules = {
360
517
  "ensure-custom-hooks-using-other-hooks": ensure_custom_hooks_using_other_hooks_default,
361
518
  "ensure-use-callback-has-non-empty-deps": ensure_use_callback_has_non_empty_deps_default,
362
519
  "ensure-use-memo-has-non-empty-deps": ensure_use_memo_has_non_empty_deps_default,
520
+ "no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default,
521
+ "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default,
363
522
  "prefer-use-state-lazy-initialization": prefer_use_state_lazy_initialization_default
364
523
  };
365
524
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks-extra",
3
- "version": "1.5.25",
3
+ "version": "1.5.26-next.1",
4
4
  "description": "ESLint React's ESLint plugin for React Hooks related rules.",
5
5
  "homepage": "https://github.com/rel1cx/eslint-react",
6
6
  "bugs": {
@@ -39,13 +39,13 @@
39
39
  "@typescript-eslint/type-utils": "^7.16.0",
40
40
  "@typescript-eslint/types": "^7.16.0",
41
41
  "@typescript-eslint/utils": "^7.16.0",
42
- "@eslint-react/core": "1.5.25",
43
- "@eslint-react/shared": "1.5.25",
44
- "@eslint-react/jsx": "1.5.25",
45
- "@eslint-react/tools": "1.5.25",
46
- "@eslint-react/types": "1.5.25",
47
- "@eslint-react/ast": "1.5.25",
48
- "@eslint-react/var": "1.5.25"
42
+ "@eslint-react/ast": "1.5.26-next.1",
43
+ "@eslint-react/jsx": "1.5.26-next.1",
44
+ "@eslint-react/tools": "1.5.26-next.1",
45
+ "@eslint-react/types": "1.5.26-next.1",
46
+ "@eslint-react/var": "1.5.26-next.1",
47
+ "@eslint-react/shared": "1.5.26-next.1",
48
+ "@eslint-react/core": "1.5.26-next.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "string-ts": "2.2.0",