eslint-plugin-react-x 5.13.0 → 5.13.2

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/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ESLint, Linter } from "eslint";
2
-
3
2
  //#region src/index.d.ts
4
3
  type ConfigName = "disable-experimental" | "disable-type-checked" | "disable-conflict-eslint-plugin-react" | "disable-conflict-eslint-plugin-react-hooks" | "recommended" | "recommended-type-checked" | "recommended-typescript" | "strict" | "strict-type-checked" | "strict-typescript";
5
4
  declare const finalPlugin: ESLint.Plugin & {
package/dist/index.js CHANGED
@@ -144,7 +144,7 @@ const rules$6 = {
144
144
  //#endregion
145
145
  //#region package.json
146
146
  var name$6 = "eslint-plugin-react-x";
147
- var version = "5.13.0";
147
+ var version = "5.13.2";
148
148
 
149
149
  //#endregion
150
150
  //#region src/utils/create-rule.ts
@@ -1348,6 +1348,33 @@ function hasRefLikeNameInChain(node) {
1348
1348
  }
1349
1349
  return false;
1350
1350
  }
1351
+ /**
1352
+ * Check if the root identifier of a member-expression chain (or the
1353
+ * identifier itself) is initialized directly from a `useRef()` call, e.g.
1354
+ * `const mounted = useRef(false); mounted.current = true;`.
1355
+ *
1356
+ * This catches refs regardless of naming convention, complementing
1357
+ * {@link hasRefLikeNameInChain}.
1358
+ * @param context The ESLint rule context.
1359
+ * @param node The AST node to inspect (an identifier or member-expression chain).
1360
+ */
1361
+ function isInitializedFromUseRef(context, node) {
1362
+ const rootId = node.type === AST_NODE_TYPES.Identifier ? node : Extract.getRootIdentifier(node);
1363
+ if (rootId == null) return false;
1364
+ const initNode = resolve(context, rootId);
1365
+ return initNode != null && initNode.type === AST_NODE_TYPES.CallExpression && core.isUseRefCall(context, initNode);
1366
+ }
1367
+ /**
1368
+ * Check if a mutated expression chain should be exempt from immutability
1369
+ * checks because it is rooted at a ref: either by naming convention
1370
+ * ({@link hasRefLikeNameInChain}) or because it is initialized from a
1371
+ * `useRef()` call ({@link isInitializedFromUseRef}).
1372
+ * @param context The ESLint rule context.
1373
+ * @param node The AST node to inspect (an identifier or member-expression chain).
1374
+ */
1375
+ function isRefLikeChain(context, node) {
1376
+ return hasRefLikeNameInChain(node) || isInitializedFromUseRef(context, node);
1377
+ }
1351
1378
 
1352
1379
  //#endregion
1353
1380
  //#region src/rules/immutability/immutability.ts
@@ -1388,7 +1415,7 @@ function create$48(context) {
1388
1415
  pushMutationSite(node, left);
1389
1416
  return;
1390
1417
  case AST_NODE_TYPES.MemberExpression: {
1391
- if (hasRefLikeNameInChain(left)) return;
1418
+ if (isRefLikeChain(context, left)) return;
1392
1419
  const rootId = Extract.getRootIdentifier(left);
1393
1420
  if (rootId == null) return;
1394
1421
  pushMutationSite(node, rootId);
@@ -1400,7 +1427,7 @@ function create$48(context) {
1400
1427
  const callee = Extract.unwrap(node.callee);
1401
1428
  if (callee.type === AST_NODE_TYPES.MemberExpression) {
1402
1429
  const propName = Extract.getPropertyName(callee.property);
1403
- if (propName != null && MUTATING_METHODS.has(propName) && !hasRefLikeNameInChain(callee.object)) {
1430
+ if (propName != null && MUTATING_METHODS.has(propName) && !isRefLikeChain(context, callee.object)) {
1404
1431
  const rootId = Extract.getRootIdentifier(callee.object);
1405
1432
  if (rootId != null) pushMutationSite(node, rootId);
1406
1433
  }
@@ -1459,7 +1486,7 @@ function create$48(context) {
1459
1486
  if (node.operator !== "delete") return;
1460
1487
  const arg = Extract.unwrap(node.argument);
1461
1488
  if (arg.type !== AST_NODE_TYPES.MemberExpression) return;
1462
- if (hasRefLikeNameInChain(arg)) return;
1489
+ if (isRefLikeChain(context, arg)) return;
1463
1490
  const rootId = Extract.getRootIdentifier(arg);
1464
1491
  if (rootId == null) return;
1465
1492
  pushMutationSite(node, rootId);
@@ -1472,7 +1499,7 @@ function create$48(context) {
1472
1499
  pushMutationSite(node, arg);
1473
1500
  return;
1474
1501
  case AST_NODE_TYPES.MemberExpression: {
1475
- if (hasRefLikeNameInChain(arg)) return;
1502
+ if (isRefLikeChain(context, arg)) return;
1476
1503
  const rootId = Extract.getRootIdentifier(arg);
1477
1504
  if (rootId == null) return;
1478
1505
  pushMutationSite(node, rootId);
@@ -4360,9 +4387,9 @@ var refs_default = createRule({
4360
4387
  docs: { description: "Validates correct usage of refs by checking that 'ref.current' is not read or written during render." },
4361
4388
  messages: {
4362
4389
  duplicateRefInit: "Ref is initialized more than once during render. Only a single 'if (ref.current == null)' initialization is allowed; move any additional initialization into an effect or event handler.",
4363
- readDuringRender: "Do not read 'ref.current' during render. Refs are not available during rendering and their values may be stale or inconsistent. Move this read into an effect or event handler.",
4364
- refPassedToFunction: "Passing a ref to a function may cause its value to be read during render. Pass 'ref.current' instead if the function only needs the value, or move the call into an effect.",
4365
- writeDuringRender: "Do not write to 'ref.current' during render. Refs should only be mutated in effects or event handlers. Move this write into an effect or event handler."
4390
+ readDuringRender: "Cannot access refs during render",
4391
+ refPassedToFunction: "Passing a ref to a function may read its value during render",
4392
+ writeDuringRender: "Cannot update ref during render"
4366
4393
  },
4367
4394
  schema: []
4368
4395
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "5.13.0",
3
+ "version": "5.13.2",
4
4
  "description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
5
5
  "keywords": [
6
6
  "react",
@@ -45,12 +45,12 @@
45
45
  "string-ts": "^2.3.1",
46
46
  "ts-api-utils": "^2.5.0",
47
47
  "ts-pattern": "^5.9.0",
48
- "@eslint-react/core": "5.13.0",
49
- "@eslint-react/ast": "5.13.0",
50
- "@eslint-react/eslint": "5.13.0",
51
- "@eslint-react/var": "5.13.0",
52
- "@eslint-react/jsx": "5.13.0",
53
- "@eslint-react/shared": "5.13.0"
48
+ "@eslint-react/ast": "5.13.2",
49
+ "@eslint-react/core": "5.13.2",
50
+ "@eslint-react/eslint": "5.13.2",
51
+ "@eslint-react/jsx": "5.13.2",
52
+ "@eslint-react/shared": "5.13.2",
53
+ "@eslint-react/var": "5.13.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/react": "^19.2.17",
@@ -59,12 +59,12 @@
59
59
  "eslint": "^10.6.0",
60
60
  "react": "^19.2.7",
61
61
  "react-dom": "^19.2.7",
62
- "tsdown": "^0.22.3",
62
+ "tsdown": "^0.22.4",
63
63
  "tsl": "^1.0.30",
64
64
  "tsl-dx": "^0.13.2",
65
65
  "typescript": "6.0.3",
66
- "@local/configs": "0.0.0",
67
- "@local/eff": "0.0.0"
66
+ "@local/eff": "0.0.0",
67
+ "@local/configs": "0.0.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "eslint": "*",