# Changelog (/docs/changelog) ## v5.18.3 (2026-08-06) [#v5183-2026-08-06] ### ๐Ÿž Fixes [#-fixes] * `react-x/no-nested-component-definitions`: narrowed the `with*` HOC detection in the fallback name resolution to well-known wrappers only (react-router v5's `withRouter`, Formik's `withFormik`, and recompose's `withProps`, `withState`, `withHandlers`, and `withLifecycle`) โ€” custom HOCs following the `with*` naming convention are no longer treated as component wrappers. (#1929) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal] * Bumped `typescript-eslint` to `8.66.0` and `next` to `16.3.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.18.2...v5.18.3](https://github.com/Rel1cx/eslint-react/compare/v5.18.2...v5.18.3) ## v5.18.2 (2026-08-05) [#v5182-2026-08-05] ### ๐Ÿž Fixes [#-fixes-1] * `react-x/no-nested-component-definitions`: fixed a regression where nested components wrapped in `useCallback` (e.g. `const C = useCallback(() =>
, []);`) were no longer reported โ€” the rule now resolves the component name through well-known component wrappers (`memo`, `forwardRef`, `useCallback`, `observer`, react-redux's `connect`, Relay's `create*Container` helpers, Apollo's `graphql`, and `with*` HOCs, including curried forms like `connect(...)(Component)`) up to the enclosing variable declarator, and no longer misreports array method callbacks (`flatMap`, `forEach`, `reduce`, etc.) in list rendering patterns. (#1928, closes #1927) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-1] * Bumped `effect` to `3.22.1`, `eslint-plugin-jsdoc` to `63.3.3`, `textlint` to `15.8.0`, `js-yaml` to `4.3.1`, `axios` to `1.19.0`, `nx` to `23.1.1`, `vite` to `8.2.0`, `@vitejs/plugin-react` to `6.0.5`, `fumadocs` to `16.14.0`, `fumadocs-mdx` to `15.2.2`, `preact` to `10.29.8`, `globals` to `17.9.0`, `lucide-react` to `1.28.0`, `@types/react` to `19.2.18`, `@types/react-dom` to `19.2.4`, and `pnpm` to `11.20.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.18.1...v5.18.2](https://github.com/Rel1cx/eslint-react/compare/v5.18.1...v5.18.2) ## v5.18.1 (2026-07-30) [#v5181-2026-07-30] ### ๐Ÿ“ Documentation [#-documentation] * Documented the `additionalRefHooks` shared setting in the affected rule docs. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-2] * `@eslint-react/ast`: added `Traverse.findEnclosingTryBlock`, extracted from `react-x/error-boundaries`. * Replaced `@eslint/compat` with `@eslint/config-helpers`. * Bumped `eslint` to `10.8.0`, `eslint-plugin-jsdoc` to `63.3.2`, `tsdown` to `0.22.14`, `next` to `16.2.12`, `fumadocs` to `16.13.0`, `postcss` to `8.5.25`, and `pnpm` to `11.18.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.18.0...v5.18.1](https://github.com/Rel1cx/eslint-react/compare/v5.18.0...v5.18.1) ## v5.18.0 (2026-07-23) [#v5180-2026-07-23] ### โœจ New [#-new] * `@eslint-react/core`: added `isUseRefLikeCall` and a new `additionalRefHooks` setting for declaring custom ref-creating hooks; the following rules now recognize them: (#1922, closes #1904) * `react-x/refs` * `react-x/immutability` * `react-x/set-state-in-effect` * `react-naming-convention/ref-name` * `react-debug/is-from-ref` ### ๐Ÿ“ Documentation [#-documentation-1] * Updated rule docs to match current rule sources. (#1920) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-3] * `@local/testkit`: simplified internals. * `react-x`: extracted a shared `createImplicitPropListener` helper used by `no-implicit-children`, `no-implicit-key`, and `no-implicit-ref`. (#1923) * Bumped `tsdown` to `0.22.13`, `typescript-eslint` to `8.65.0`, `eslint-plugin-jsdoc` to `63.2.0`, `import-integrity-lint` to `1.2.0`, `react` to `19.2.8`, `next` to `16.2.11`, and `postcss` to `8.5.21`. * Replaced `vite-node` with `nub` for running workspace scripts. (#1919) * Unified JSDoc comment style of exported APIs in `@eslint-react/ast` and `@eslint-react/core`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.17.3...v5.18.0](https://github.com/Rel1cx/eslint-react/compare/v5.17.3...v5.18.0) ## v5.17.3 (2026-07-20) [#v5173-2026-07-20] ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-4] * `@eslint-react/ast`: reworked the `Extract` API โ€” replaced `getRootIdentifier` with the position-based `getIdentifierAt`, renamed `getStaticPropertyName` to `getPropertyName` (with a `min`/`max` effort option), and added `findProperty` for finding properties in nested object expressions; added `Check.isConditional` for matching conditional expressions and control flow statements. (#1918) * Bumped `eslint-plugin-jsdoc` to `63.1.0`, `expect-type` to `1.4.0`, `@preact/preset-vite` to `2.10.6`, and `pnpm` to `11.15.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.17.2...v5.17.3](https://github.com/Rel1cx/eslint-react/compare/v5.17.2...v5.17.3) ## v5.17.2 (2026-07-19) [#v5172-2026-07-19] ### ๐Ÿ“ Documentation [#-documentation-2] * `@eslint-react/kit`: added a README with quick start and API overview. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-5] * `@eslint-react/core`: migrated `JsxDetectionHint` and related JSX detection helpers from `@eslint-react/jsx`. (#1913) * `@eslint-react/jsx`: consolidated helpers into focused `attribute`, `children`, `element`, and `text` modules. (#1914) * `@eslint-react/var`: renamed `computeObjectType` to `resolveObjectType`. * `@local/testkit`: extracted shared test helpers into a new local package. (#1915) * Bumped `tsdown` to `0.22.9`, `eslint-plugin-jsdoc` to `63.0.14`, and `pnpm` to `11.13.1`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.17.1...v5.17.2](https://github.com/Rel1cx/eslint-react/compare/v5.17.1...v5.17.2) ## v5.17.1 (2026-07-17) [#v5171-2026-07-17] ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-6] * `react-jsx/no-key-after-spread`: reworked the attribute scan to a pipeline style using `dropWhile` and `not` from `@local/eff`, `Check.is` from `@eslint-react/ast`, and the new `isAttribute` helper from `@eslint-react/jsx`. (#1912) * `@eslint-react/jsx`: added `isAttribute` for matching JSX attributes by name. * `@local/eff`: added `dropWhile` and `takeWhile`. * Bumped `tsdown` to `0.22.8`, `tsl-dx` to `0.13.3`, `import-integrity-lint` to `1.1.4`, `fumadocs` to `16.11.5`, and `fumadocs-mdx` to `15.2.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.17.0...v5.17.1](https://github.com/Rel1cx/eslint-react/compare/v5.17.0...v5.17.1) ## v5.17.0 (2026-07-17) [#v5170-2026-07-17] ### ๐Ÿž Fixes [#-fixes-2] * `react-jsx/no-leaked-dollar`: the intentional-`$` exemption (e.g. `
${price}
`) is no longer defeated by surrounding whitespace or empty siblings โ€” a lone `$` before a single expression is now allowed whenever all other siblings are non-substantive. (#1911) * `react-jsx/no-leaked-semicolon`: consecutive leaked semicolons (e.g. `;;`) at the start of a JSX text node are now detected. (#1911) ### ๐Ÿ“ Documentation [#-documentation-3] * `react-x/no-unnecessary-use-prefix`: reorganized the rule examples. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-7] * `react-jsx`: extracted the shared `find-create-element-children-prop` and `remove-jsx-attribute` rule helpers, removed dead `Literal` visitors from `no-comment-textnodes` and `no-leaked-semicolon`, simplified the `no-key-after-spread` attribute scan, and hoisted `no-useless-fragment` detection and fix helpers to module level. (#1911) * `@local/eff`: synced the `Function` module with effect and added missing `@category` tags. * Unified JSDoc comment style across packages. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.16.1...v5.17.0](https://github.com/Rel1cx/eslint-react/compare/v5.16.1...v5.17.0) ## v5.16.1 (2026-07-16) [#v5161-2026-07-16] ### ๐Ÿž Fixes [#-fixes-3] * `react-jsx/no-children-prop`: `React.createElement` calls whose props argument is wrapped in a TypeScript type assertion (e.g. `{ children: "x" } as Props`) are now reported; computed property keys written as template literals (e.g. `{ [`children`]: "x" }`) are now recognized as the `children` prop; fixed a false positive where a computed identifier key in a `createElement` props object (e.g. `{ [propName]: "Children" }`) was treated as the static `children` prop; the suggestion fix now escapes JSX-sensitive characters (`<`, `>`, `{`, `}`, `&`) when moving a string `children` prop value into element content. (#1910) * `react-jsx/no-children-prop-with-children`: same `createElement` edge-case fixes as `no-children-prop`. (#1910) * `react-jsx/no-useless-fragment`: `allowExpressions: false` now only flags fragments with a single expression child, matching the option's documented behavior, instead of flagging any fragment inside a JSX element; fragments with spread attributes (e.g. ``) are no longer auto-fixed; the auto-fixer now removes leading indentation when collapsing whitespace-only fragments. (#1910) * `react-jsx/no-leaked-dollar`: `$` character references (`$`, `$`) are no longer treated as leaked dollar signs; only a literal `$` in the source is reported. (#1910) * `react-jsx/no-leaked-semicolon`: leaked semicolons followed by spaces or tabs before a newline, including CRLF line endings, are now detected. (#1910) * `react-x/immutability`: added `useHistory` to known navigation hooks, so navigation methods such as `.push()` are not treated as in-place mutations inside frozen callbacks. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-8] * `@eslint-react/ast`: added `Extract.getStaticPropertyName` for resolving static property names from object properties. (#1910) **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.16.0...v5.16.1](https://github.com/Rel1cx/eslint-react/compare/v5.16.0...v5.16.1) ## v5.16.0 (2026-07-16) [#v5160-2026-07-16] ### โœจ New [#-new-1] * `@eslint-react/core`: added support for hook calls written as tagged template literals. (#1909) ```tsx const x = useMotionValue(100); const transform = useMotionTemplate`transform(${x}px)`; // ^^^ tagged template literal hook call ``` * `@eslint-react/jsx`: `findAttribute` now resolves nested spread identifiers and nested object expression spreads. (#1908) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-9] * Added tests and per-rule changelogs for tagged template literal hook calls. (#1909) **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.15.0...v5.16.0](https://github.com/Rel1cx/eslint-react/compare/v5.15.0...v5.16.0) ## v5.15.0 (2026-07-15) [#v5150-2026-07-15] ### ๐Ÿ“ Documentation [#-documentation-4] * Added a FAQ entry on improving analyzer accuracy to the website. (#1907) * Fixed inconsistencies and omissions in internal documentation. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-10] * Bumped `typescript-eslint` to `8.64.0`, `nx` to `23.1.0`, `eslint-plugin-package-json` to `1.6.0`, and `pnpm` to `11.13.0`. * Enabled `strictBooleanExpressions` in TSL and synchronized sample rule configurations. (#1907) * Removed the website-specific changelog file. * Switched CI workflows to use `pnpm/action-setup` instead of installing pnpm globally via npm. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.10...v5.15.0](https://github.com/Rel1cx/eslint-react/compare/v5.14.10...v5.15.0) ## v5.14.10 (2026-07-15) [#v51410-2026-07-15] ### ๐Ÿž Fixes [#-fixes-4] * `@eslint-react/ast`: `Extract.getCalleeName` now returns `null` for computed member expressions (e.g. `obj[foo]()`, `obj["foo"]()`, `obj[`foo`]()`) instead of the property name, so callers don't treat dynamically chosen methods as static method names. (#1906) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-11] * Added unit tests for `Extract.getCalleeName`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.9...v5.14.10](https://github.com/Rel1cx/eslint-react/compare/v5.14.9...v5.14.10) ## v5.14.9 (2026-07-15) [#v5149-2026-07-15] ### ๐Ÿž Fixes [#-fixes-5] * `@eslint-react/ast`: removed `Extract.getPropertyName` and added `Extract.getCalleeName` for simpler callee name resolution. (#1905) * Rules that match calls by method name no longer treat computed string-literal property access as a static match (e.g. `obj["foo"]()` is no longer resolved to `"foo"`). This avoids relying on the runtime value of computed keys and aligns callee matching across the codebase. Affected rules: * `react-dom/no-dangerously-set-innerhtml` * `react-dom/no-find-dom-node` * `react-dom/no-flush-sync` * `react-web-api/no-leaked-event-listener` * `react-web-api/no-leaked-fetch` * `react-x/globals` * `react-x/immutability` * `core.isJsxLike`: no longer treats `React['createElement']` calls as JSX-like, since the callee is accessed through a computed member expression. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-12] * Simplified callee name checks across `core`, `react-dom`, `react-web-api`, and `react-x` rules using `Extract.getCalleeName`. * Bumped `@effect/platform`, `effect`, `fumadocs-core`, `fumadocs-mdx`, `fumadocs-ui`, `postcss`, `pnpm`, and `tsdown`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.8...v5.14.9](https://github.com/Rel1cx/eslint-react/compare/v5.14.8...v5.14.9) ## v5.14.8 (2026-07-14) [#v5148-2026-07-14] ### ๐Ÿ“ Documentation [#-documentation-5] * `react-x`: refreshed the React Compiler diff reports. (#1903) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-13] * `react-x`: moved the purity and refs resolvers into `lib.ts`. (#1902) * Bumped `tsdown`, `postcss`, and `fumadocs`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.7...v5.14.8](https://github.com/Rel1cx/eslint-react/compare/v5.14.7...v5.14.8) ## v5.14.7 (2026-07-13) [#v5147-2026-07-13] ### ๐Ÿž Fixes [#-fixes-6] * `react-x/immutability`: ignore navigation hook methods (e.g. `useNavigate`, `useNavigation`) as mutations. (#1901) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-14] * Refreshed `pnpm` lockfile. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.6...v5.14.7](https://github.com/Rel1cx/eslint-react/compare/v5.14.6...v5.14.7) ## v5.14.6 (2026-07-13) [#v5146-2026-07-13] ### ๐Ÿž Fixes [#-fixes-7] * `react-x/immutability`: ignore `useRouter()` navigation methods (e.g. `.push()`) as mutations when they appear inside frozen callbacks; aliases created through variable declarators are also recognized. (#1898) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-15] * Added `Check.isExpression` to `@eslint-react/ast` along with unit tests. * Bumped `eslint`, `nx`, `dompurify`, and `pnpm`. * Restored standalone quality workflows. * Simplified `react-x/immutability` analysis helpers by sharing initializer provenance checks for `useRef()` and `useRouter()` and using AST parent traversal for function-boundary detection. * Started running CI tests on Node.js 26. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.5...v5.14.6](https://github.com/Rel1cx/eslint-react/compare/v5.14.5...v5.14.6) ## v5.14.5 (2026-07-11) [#v5145-2026-07-11] ### ๐Ÿ“ Documentation [#-documentation-6] * Temporarily disabled the Bluesky embed on the community page to avoid API rate limits. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-16] * Consolidated the `check:configs` and `check:docs` scripts into a single `check:rules` script. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.4...v5.14.5](https://github.com/Rel1cx/eslint-react/compare/v5.14.4...v5.14.5) ## v5.14.4 (2026-07-11) [#v5144-2026-07-11] ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-17] * Fixed rule discovery in documentation and configuration checks to exclude helper modules from rule entry files. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.3...v5.14.4](https://github.com/Rel1cx/eslint-react/compare/v5.14.3...v5.14.4) ## v5.14.3 (2026-07-11) [#v5143-2026-07-11] ### ๐Ÿž Fixes [#-fixes-8] * `react-x/immutability`: stopped treating mutations of resolvable global and module bindings as captured local mutations. (#1897) * `react-x/immutability`: followed variable-declarator aliases when resolving mutation targets, fixing missed mutations through aliases created inside callbacks. (#1897) * `react-x/immutability`: followed `useRef` provenance through variable-declarator aliases, preventing false positives for ref mutations through locally aliased refs. (#1897) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-18] * `react-x/immutability`: separated AST fact collection from captured-mutation effect inference and reporting. (#1897) * Synchronized the `react-x/immutability` specification and IMPL-SPEC report with the current React Compiler validation pass, and expanded behavior-boundary coverage. (#1897) **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.2...v5.14.3](https://github.com/Rel1cx/eslint-react/compare/v5.14.2...v5.14.3) ## v5.14.2 (2026-07-11) [#v5142-2026-07-11] ### ๐Ÿž Fixes [#-fixes-9] * `react-x/globals`: added detection for global writes through destructuring assignments and property deletion with `delete`. (#1896) * `react-x/globals`: propagated render-time global mutation effects through directly called helpers and stable local aliases. (#1896) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-19] * Expanded behavior-boundary coverage for `react-debug` component and source detection, `react-naming-convention` naming rules, and `react-x/immutability` React Compiler fixtures. * Strengthened documentation verification and added formatting, configuration, architecture, MDX, website type, and production build checks to CI. * Gated publishing on the check, test, and workflow security jobs, including for application, example, and configuration changes. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.1...v5.14.2](https://github.com/Rel1cx/eslint-react/compare/v5.14.1...v5.14.2) ## v5.14.1 (2026-07-11) [#v5141-2026-07-11] ### ๐Ÿž Fixes [#-fixes-10] * `react-rsc/function-definition`: fixed invalid async autofixes for object and class methods with local `'use server'` directives, including generator and computed methods; accessors and constructors are now reported without an unsafe fix. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-20] * Added behavior-boundary tests for `react-rsc/function-definition`, covering directive placement, export resolution, function forms, and autofix behavior. * Cleaned up redundant code and comments in `react-rsc/function-definition` and `react-x/unsupported-syntax`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.14.0...v5.14.1](https://github.com/Rel1cx/eslint-react/compare/v5.14.0...v5.14.1) ## v5.14.0 (2026-07-10) [#v5140-2026-07-10] ### โœจ New [#-new-2] * `react-x/refs`: added render-reachability support for function declarations, IIFEs, synchronous array callbacks, and render-time callbacks passed to `useMemo` and `useReducer`. (#1895) * `react-x/refs`: added lazy-initialization support for explicit `undefined` guards and for null guards enclosing additional nested conditions. (#1895) ### ๐Ÿž Fixes [#-fixes-11] * `react-x/refs`: reworked render-time call analysis as an unbounded fixed-point propagation, removing the previous 50-iteration cap. (#1895) * `react-x/refs`: tightened inverted lazy-initialization handling so the non-null branch must unconditionally return or throw. (#1895) * `react-x/refs`: stopped treating `!ref.current` as a null guard because initialized refs may contain falsy values. (#1895) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-21] * `react-x/refs`: refactored ref aliases, function bindings, JSX refs, and duplicate initialization tracking to use scoped ESLint variable identities and position-aware binding events instead of file-wide identifier names. (#1895) * Added behavior-boundary tests for `react-x/immutability` and documented them in the spec diff report. * Updated build scripts. * Bumped `@effect/language-service` to `^0.86.5`. * Bumped `preact` to `^10.29.7`. * Bumped `vite` to `^8.1.4` in example apps. * Bumped `dprint` JSON plugin to `^0.23.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.13.2...v5.14.0](https://github.com/Rel1cx/eslint-react/compare/v5.13.2...v5.14.0) ## v5.13.2 (2026-07-09) [#v5132-2026-07-09] ### ๐Ÿž Fixes [#-fixes-12] * `react-x/immutability`: fixed false positive on `ref.current` write inside `useEffect`. (#1894) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-22] * Bumped `@types/node` to `^26.1.1`. * Bumped `preact` to `^10.29.6`. * Bumped `tsdown` to `^0.22.4`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.13.1...v5.13.2](https://github.com/Rel1cx/eslint-react/compare/v5.13.1...v5.13.2) ## v5.13.1 (2026-07-09) [#v5131-2026-07-09] ### ๐Ÿž Fixes [#-fixes-13] * `react-x/refs`: aligned error message wording for `readDuringRender`, `writeDuringRender`, and `refPassedToFunction` with the React Compiler specification. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.13.0...v5.13.1](https://github.com/Rel1cx/eslint-react/compare/v5.13.0...v5.13.1) ## v5.13.0 (2026-07-09) [#v5130-2026-07-09] ### โœจ New [#-new-3] * `react-x/refs` now detects nested property writes on a ref's value (e.g. `ref.current.inner = value`), which are now reported as `writeDuringRender` instead of being misclassified as a read. * `react-x/refs` now tracks functions bound to (and called through) simple object-member-expression targets (e.g. `object.foo = () => ref.current; object.foo();`), closing a gap in the render-reachability analysis that previously only covered plain variable bindings. * `react-x/refs` now detects `ref.current` accesses inside the lazy initializer function passed directly as `useState`'s first argument, since it runs synchronously during the initial render unlike other hook-callback arguments. * `react-x/refs` now exempts calls to a function named `render` (e.g. `props.render(ref)`, a common render-prop pattern) from the `refPassedToFunction` diagnostic, alongside the existing `mergeRefs`/hook exemptions. ### ๐Ÿž Fixes [#-fixes-14] * Improved `react-x/refs` lazy-init guard-block detection so it is direction-aware: inside the branch of an `if (ref.current == null)`-style guard that is guaranteed to see `ref.current` as null, only a direct write is treated as the (single) valid initialization; reads or values passed to a function there are still reported. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-23] * Refactored `react-x/refs` internals, replacing `isRefCurrentNullCheck` with `getRefCurrentNullCheckBranch` in `lib.ts`. * Upgraded `fumadocs` packages and `preact`. * Cleaned up redundant code in the `react-debug/jsx` rule. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.12.2...v5.13.0](https://github.com/Rel1cx/eslint-react/compare/v5.12.2...v5.13.0) ## v5.12.1 (2026-07-08) [#v5121-2026-07-08] ### ๐Ÿ“ Documentation [#-documentation-7] * Fixed `react-x/immutability` rule description in docs. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-24] * Cleaned up redundant code in some rules. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.12.0...v5.12.1](https://github.com/Rel1cx/eslint-react/compare/v5.12.0...v5.12.1) ## v5.12.0 (2026-07-08) [#v5120-2026-07-08] ### โœจ New [#-new-4] * Reworked `react-x/immutability` to align with the React Compiler's `ValidateNoFreezingKnownMutableFunctions` validation pass: it now detects functions that (transitively) mutate a captured local variable and reports them when passed as a JSX prop, passed as a hook argument, or returned from a hook. (#1891) ### ๐Ÿ“ Documentation [#-documentation-8] * Cleaned up the rule relations table. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-25] * Bumped `typescript-eslint` packages to `^8.63.0`. * Bumped `eslint-plugin-perfectionist` to `^5.10.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.11.3...v5.12.0](https://github.com/Rel1cx/eslint-react/compare/v5.11.3...v5.12.0) ## v5.11.3 (2026-07-07) [#v5113-2026-07-07] ### ๐Ÿž Fixes [#-fixes-15] * Fixed `FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsClassProperty` checking for object `Property` nodes instead of class `PropertyDefinition` nodes, so functions defined as class fields are now correctly excluded when the hint is set. (#1890) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-26] * Renamed fix helpers and formatted `MessageID` types. * Inlined local string constants in rule implementations. * Bumped `eslint-plugin-jsdoc`, `typedoc`, `undici` and `pnpm`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.11.2...v5.11.3](https://github.com/Rel1cx/eslint-react/compare/v5.11.2...v5.11.3) ## v5.11.2 (2026-07-05) [#v5112-2026-07-05] ### ๐Ÿ“ Documentation [#-documentation-9] * Updated rule documentation for React introspection APIs (`react-x/no-children-count`, `react-x/no-children-for-each`, `react-x/no-children-map`, `react-x/no-children-only`, `react-x/no-children-to-array`, and `react-x/no-clone-element`) with clearer guidance on why child introspection creates fragile component coupling and links to Astryx's `no-react-introspection` rule. (#1889) * Updated the function-component collector sequence diagram on the website. * Updated `THIRD-PARTY-LICENSE` file. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.11.0...v5.11.2](https://github.com/Rel1cx/eslint-react/compare/v5.11.0...v5.11.2) ## v5.11.0 (2026-07-05) [#v5110-2026-07-05] ### โœจ New [#-new-5] * `react-x/refs` now detects ref mutations/reads inside helper functions that are called (directly, or through a simple variable alias) during render, closing a gap where any nested function was previously treated as a safe boundary regardless of whether it was actually invoked during render. * `react-x/refs` now reports a second guarded ref initialization: only a single `if (ref.current == null) { ref.current = ... }` guarded initialization is allowed per ref per component/hook, and a second guarded write (in the same or a different `if` block) is reported as `duplicateRefInit`. * `react-x/refs` now supports `.current` accesses whose base is a member expression that looks like a ref (e.g. `props.ref.current`), not just a plain identifier. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-27] * Added unit tests for `packages/ast/src/check.ts`. * Bumped `@effect/language-service` to `^0.86.4` and `preact` to `^10.29.4`. * Refactored `react-x/static-components` internals without changing behavior: `findVariableForIdentifier` now delegates to `@typescript-eslint/utils/ast-utils`'s `findVariable` instead of a hand-rolled scope-chain walk, `resolveDynamicValue` was split into `findDynamicCreationSite` and `findReassignmentCreationSite`, and render-boundary/JSX-candidate handling was extracted into dedicated helpers. * Unified the signatures of `Check.isDirective` and `Check.isIdentifier` in `@eslint-react/ast`: both now take the node as the first argument and an optional `name` as the second, replacing the previous curried `(name) => (node) => boolean` shape. Removed `Check.isStringLiteral`; use `ts-pattern`'s `isMatching` or an inline type guard instead. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.10.4...v5.11.0](https://github.com/Rel1cx/eslint-react/compare/v5.10.4...v5.11.0) ## v5.10.4 (2026-07-04) [#v5104-2026-07-04] ### ๐Ÿž Fixes [#-fixes-16] * Fixed `react-x/no-misused-capture-owner-stack` not recognizing `process.env.NODE_ENV` checks wrapped in TypeScript type expressions such as `(process.env as any).NODE_ENV`. (#1813) * Fixed `Extract.getFullyQualifiedName` to unwrap `TSAsExpression`, `TSTypeAssertion`, `TSNonNullExpression`, and `ChainExpression` before resolving names. This improves name resolution for rules that identify React APIs or collect component/hook names through type-wrapped expressions. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.10.3...v5.10.4](https://github.com/Rel1cx/eslint-react/compare/v5.10.3...v5.10.4) ## v5.10.3 (2026-07-04) [#v5103-2026-07-04] ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-28] * Bumped `typescript-eslint` packages to `^8.62.1`. * Bumped `@effect/language-service` to `^0.86.3`. * Bumped `undici` and `undici-types` to `^8.6.0`. * Updated the `@eslint-react/eslint-plugin` package description. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.10.2...v5.10.3](https://github.com/Rel1cx/eslint-react/compare/v5.10.2...v5.10.3) ## v5.10.2 (2026-07-03) [#v5102-2026-07-03] ### ๐Ÿž Fixes [#-fixes-17] * Fixed an issue where several rules treated computed identifier keys in spread props (e.g. `
`) as static prop names. The actual property name is the runtime value of the variable; computed string literal keys are still recognized. Affected rules: * `react-x/no-missing-key` * `react-jsx/no-children-prop-with-children` * `react-jsx/no-children-prop` * `react-jsx/no-useless-fragment` * `react-dom/no-dangerously-set-innerhtml-with-children` * `react-dom/no-dangerously-set-innerhtml` * `react-dom/no-missing-button-type` * `react-dom/no-missing-iframe-sandbox` * `react-dom/no-string-style-prop` * `react-dom/no-unsafe-iframe-sandbox` * `react-dom/no-unsafe-target-blank` * `react-dom/no-void-elements-with-children` * `react-web-api/no-leaked-event-listener` * `react-web-api/no-leaked-fetch` * Fixed `react-x/unsupported-syntax` to no longer report IIFEs in JSX. This makes the rule consistent with the upstream [`react-hooks/unsupported-syntax`](https://react.dev/reference/eslint-plugin-react-hooks/lints/unsupported-syntax) and removes the `iife` message. ### โœจ New [#-new-6] * `react-x/unsupported-syntax` now detects `eval` calls via `globalThis.eval`, `globalThis["eval"]`, and type assertions like `(globalThis as any).eval`. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-29] * Added an optional `resolve` parameter to `Extract.getPropertyName` so callers can control how identifier and private identifier property names are resolved. * Added unit tests for `Extract.getPropertyName`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.10.1...v5.10.2](https://github.com/Rel1cx/eslint-react/compare/v5.10.1...v5.10.2) ## v5.10.1 (2026-07-03) [#v5101-2026-07-03] ### ๐Ÿž Fixes [#-fixes-18] * Added the missing `static-components` rule to `disable-conflict-eslint-plugin-react-hooks`, closes #1884. ### ๐Ÿ“ Documentation [#-documentation-10] * Rewrote the `noCircularEffect` recipe sample to use `@eslint-react/kit` collectors and `simpleTraverse`, and updated the recipe overview accordingly. * Removed the under construction brand assets page from the website. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-30] * Bumped `typescript-eslint`, `@types/node`, `vite`, and `tailwindcss`. * Bumped `fumadocs`, `lucide-react`, and `postcss` in the website. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.10.0...v5.10.1](https://github.com/Rel1cx/eslint-react/compare/v5.10.0...v5.10.1) ## v5.10.0 (2026-06-28) [#v5100-2026-06-28] ### ๐Ÿ“ Documentation [#-documentation-11] * Added status emoji markers to recipe and rule documentation code examples (#1882). * Fixed the v5.7.2 changelog entry for `react-x/no-unused-state`. * Updated the community projects list. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-31] * Bumped `eslint` to `^10.6.0`. * Bumped `js-yaml` workspace override to `^4.3.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.5...v5.10.0](https://github.com/Rel1cx/eslint-react/compare/v5.9.5...v5.10.0) ## v5.9.5 (2026-06-27) [#v595-2026-06-27] ### ๐Ÿž Fixes [#-fixes-19] * `Compare.isEqual` now recognizes structurally identical `CallExpression` nodes. This fixes false positives in the following rules when the compared target (event target, controller, or observed element) is derived from a function call such as `window.matchMedia('โ€ฆ')` or `getEl()`: * `react-web-api/no-leaked-event-listener` * `react-web-api/no-leaked-fetch` * `react-web-api/no-leaked-resize-observer` * `react-web-api/no-leaked-intersection-observer` **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.4...v5.9.5](https://github.com/Rel1cx/eslint-react/compare/v5.9.4...v5.9.5) ## v5.9.4 (2026-06-26) [#v594-2026-06-26] ### ๐Ÿž Fixes [#-fixes-20] * The following rules now detect member expression calls made with computed string property access (e.g. `obj["foo"]()`): * `react-x/no-array-index-key` * `react-x/no-duplicate-key` * `react-x/no-unnecessary-use-prefix` * `react-x/set-state-in-effect` * `react-x/set-state-in-render` * `react-dom/no-find-dom-node` * `react-dom/no-flush-sync` * `react-dom/no-hydrate` * `react-dom/no-render` * `react-dom/no-render-return-value` * `react-dom/no-use-form-state` * `react-web-api/no-leaked-fetch` ### ๐Ÿ“ Documentation [#-documentation-12] * Updated the community page and project list. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-32] * Unified member expression property name checks with `Extract.getPropertyName` (#1881). * Updated dependencies and switched `postinstall` to `prepare`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.3...v5.9.4](https://github.com/Rel1cx/eslint-react/compare/v5.9.3...v5.9.4) ## v5.9.3 (2026-06-25) [#v593-2026-06-25] ### ๐Ÿž Fixes [#-fixes-21] * **`ast`**: Corrected the `TSESTreeJSX` union and handling of computed member expressions (#1877). * **`jsx`**: Handled namespaced host elements and cleaned up the spread child API (#1876). ### ๐Ÿ“ Documentation [#-documentation-13] * Refined the rule feature system docs and renamed the term-based patterns document. * Renamed `import-paths.md` to `repo-path-aliases.md`. * Updated JSX type aliases and `unwrap` documentation. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-33] * Aligned `RuleContext` imports in the kit package. * Bumped `typescript-eslint` packages to `^8.62.0` and related dependencies. * Renamed scripts with numeric prefixes and renamed `verify-*` scripts to `check-*`. * Replaced `pnpm run` with `node --run` across scripts (#1879). * Replaced the website brand component with an inline logo SVG. * Restructured the test directory and added integration tests (#1880). * Updated `nx` to `^23.0.1` and `pnpm` to `11.9.0`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.2...v5.9.3](https://github.com/Rel1cx/eslint-react/compare/v5.9.2...v5.9.3) ## v5.9.2 (2026-06-23) [#v592-2026-06-23] ### ๐Ÿ“ Documentation [#-documentation-14] * Cleaned up the "Further Reading" links in the rule docs. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-34] * Switched to `pnpm/action-setup` to install Node and pnpm in CI. * Updated dependencies and the lockfile. * Updated the `baseline.json` timestamp and quality signal. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.1...v5.9.2](https://github.com/Rel1cx/eslint-react/compare/v5.9.1...v5.9.2) ## v5.9.1 (2026-06-20) [#v591-2026-06-20] ### ๐Ÿ“ Documentation [#-documentation-15] * Updated rule patterns and feature system documentation (#1875). * Refined naming convention rule docs for `context-name`, `id-name`, and `ref-name` (#1873). * Updated the example comment in the `react-x/unsupported-syntax` docs. * Removed the `ast.unwrap` example from the kit package docs. * Fixed a typo in a warning callout description. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-35] * Bumped `actions/checkout` to `v7.0.0` (#1874). * Moved `getHumanReadableKind` from the ast package into the specific rules that use it. * Moved the iterator callback position map for `react-x/no-missing-key` into `lib.ts`. * Updated `dprint` line width to `160` and reformatted the codebase. * Updated `eslint` to `^10.5.0` and bumped miscellaneous dependencies. * Updated the `dprint` JSON plugin to `v0.22.0`. * Updated the baseline and `DocsPage` styling, and pruned `pnpm` workspace excludes. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.9.0...v5.9.1](https://github.com/Rel1cx/eslint-react/compare/v5.9.0...v5.9.1) ## v5.9.0 (2026-06-13) [#v590-2026-06-13] ### โœจ New [#-new-7] * Added `react-web-api/no-leaked-intersection-observer` rule to prevent leaked `IntersectionObserver` instances in components and hooks, enabled as `warn` in the `recommended` preset (#1841, #1868). ### ๐Ÿž Fixes [#-fixes-22] * **`react-web-api/no-leaked-intersection-observer`**, **`react-web-api/no-leaked-resize-observer`**: Report when `disconnect` is only called inside the observer's own callback, since the callback may never run if the component unmounts before the element intersects or resizes (#1872). ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-36] * Improved CI configuration and updated `SECURITY.md` documentation (#1871). * Bumped `fumadocs-core` and `fumadocs-ui` to `16.10.1`. ### New Contributors [#new-contributors] * **Maikel van Dort** (@Netail) made their first contribution in #1868. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.19...v5.9.0](https://github.com/Rel1cx/eslint-react/compare/v5.8.19...v5.9.0) ## v5.8.19 (2026-06-12) [#v5819-2026-06-12] ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-37] * Simplified `isJsxLike` in core package and added behavior boundary tests (#1869). * Aligned code style in jsx package with core package (#1870). * Updated `@types/node` to `^25.9.3`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.18...v5.8.19](https://github.com/Rel1cx/eslint-react/compare/v5.8.18...v5.8.19) ## v5.8.18 (2026-06-11) [#v5818-2026-06-11] ### ๐Ÿž Fixes [#-fixes-23] * Improved key detection in `react-x/no-array-index-key` and `react-x/no-missing-key` rules (#1867). ### ๐Ÿ“ Documentation [#-documentation-16] * Removed 'See Also' sections from custom rule recipes. * Reordered AST section in kit package docs (#1866). * Formatted examples as accordions in kit package docs. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-38] * Removed `postinstall` script on the website. * Updated `textlint` rules for inclusive language. * Updated dependencies and relaxed `eslint` peer dependency. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.17...v5.8.18](https://github.com/Rel1cx/eslint-react/compare/v5.8.17...v5.8.18) ## v5.8.17 (2026-06-10) [#v5817-2026-06-10] ### ๐Ÿ“ Documentation [#-documentation-17] * Simplified project description (#1860). * Updated LICENSE copyright to include contributors (#1858). * Updated brand assets guidelines and trademark policy on the website (#1859). ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-39] * Bumped `typescript-eslint` packages to `v8.61.0` (#1863, #1864). * Cleaned up config files (#1856). * Dropped `rename-rule` script and npm script (#1857). * Updated `sponsors.svg` (#1855). * Updated `undici` and cleaned up `dprint` config (#1854). * Updated brand component and removed boilerplate on the website (#1861). * Updated scaffold script, docs and baseline (#1862). **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.16...v5.8.17](https://github.com/Rel1cx/eslint-react/compare/v5.8.16...v5.8.17) ## v5.8.16 (2026-06-07) [#v5816-2026-06-07] ### ๐Ÿž Fixes [#-fixes-24] * Aligned dependency versions across monorepo (#1853). **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.15...v5.8.16](https://github.com/Rel1cx/eslint-react/compare/v5.8.15...v5.8.16) ## v5.8.15 (2026-06-07) [#v5815-2026-06-07] ### ๐Ÿ“ Documentation [#-documentation-18] * Added under-construction callouts and refined kit pages on the website (#1850, #1851). * Removed `AGENTS.md` and `CONTRIBUTING.md` documents and references (#1848). * Updated home and third-party plugins pages on the website. * Updated issue template guidance and labels. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-40] * Bumped `@types/*` dependencies (#1852). * Relaxed checklist requirements in issue templates (#1849). **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.13...v5.8.15](https://github.com/Rel1cx/eslint-react/compare/v5.8.13...v5.8.15) ## v5.8.13 (2026-06-06) [#v5813-2026-06-06] ### ๐Ÿ“ Documentation [#-documentation-19] * Added `GoogleCloudPlatform/gke-mcp` and removed archived `antfu/shiki-stream` from community projects on the website. * Improved RSC Directives wording in documentation. * Removed the `no-multiple-children-in-title` recipe from the website. * Removed the kit beta banner from the website (#1846). ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-41] * Added `RuleListener` return type to all rule `create` functions (#1845). * Added boundary and edge case tests for `react-dom` rules, JSX rules, and `naming-convention` rules (`context-name`, `id-name`, `ref-name`). * Added identifier resolution tests for `react-x/no-leaked-conditional-rendering` (#1844). * Bumped `pnpm` and updated lockfile. * Bumped `tsdown` to `0.22.2` and updated dependencies. * Removed redundant single-argument `merge()` calls in rules (#1843). * Switched GitHub workflows to `ubuntu-latest`. * Updated website brand assets and icons. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.12...v5.8.13](https://github.com/Rel1cx/eslint-react/compare/v5.8.12...v5.8.13) ## v5.8.12 (2026-06-05) [#v5812-2026-06-05] ### ๐Ÿช„ Improvements [#-improvements] * **`jsx`**: Aligned `getChildren` with Babel's `buildChildren` and `cleanJSXElementLiteralChild` patterns, improving whitespace handling accuracy in `react-jsx/no-useless-fragment` and `react-jsx/no-children-prop` rules. Migrated child text cleanup to `@eslint-react/jsx` utilities and removed local `lib.ts` helpers. (#1836) * **`jsx`**: Removed `isPaddingWhitespace` API and added whitespace boundary tests for `react-jsx/no-useless-fragment` and `react-dom/no-dangerously-set-innerhtml-with-children` rules. (#1837) * **`jsx`**: Renamed `cleanJSXTextValue` to `collapseMultilineText` in the public API and updated `react-jsx/no-useless-fragment` to use the new name. (#1838) ### ๐Ÿ“ Documentation [#-documentation-20] * **Website**: Expanded the Brand Assets page with an icons section and formatted file names as inline code. (#1834) ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-42] * Added `scripts/generate-website-icons.py` for automated icon generation and refined logo geometry across all website assets. (#1833) * Bumped `import-integrity-lint` and `enhanced-resolve`. * Bumped `axios` to `^1.17.0` and `shiki` to `4.2.0`. * Updated pnpm lockfiles for `dompurify` and `rolldown`. * Updated rule-level changelogs for `no-useless-fragment`, `no-children-prop`, and `no-dangerously-set-innerhtml-with-children`. (#1836, #1837, #1838) **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.11...v5.8.12](https://github.com/Rel1cx/eslint-react/compare/v5.8.11...v5.8.12) ## v5.8.11 (2026-06-04) [#v5811-2026-06-04] ### ๐Ÿ“ Documentation [#-documentation-21] * Added a new **Brand Assets** page and updated Meta legal name (#1832). ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-43] * Updated default React fallback version to `19.2.7` (#1827). * Recreated logo with an open-source workflow, removing reliance on SVG assets exported by Amadine (#1831). * Removed `@fontsource/iosevka-aile` and switched to system font fallbacks. * Bumped TypeScript to `6.0.3` (#1828). * Patch bumped `@typescript-eslint/*` to `8.60.1`, `react` / `react-dom` to `19.2.7`, `next` to `16.2.7`, and `@types/react` to `19.2.16`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.10...v5.8.11](https://github.com/Rel1cx/eslint-react/compare/v5.8.10...v5.8.11) ## v5.8.10 (2026-06-02) [#v5810-2026-06-02] ### ๐Ÿž Fixes [#-fixes-25] * **`react-dom/no-unused-class-component-members`**: Aligned preset details in rule documentation (#1825). * **`react-dom/no-unsafe-iframe-sandbox`**, **`react-x/context-name`**, **`react-x/id-name`**, **`react-x/ref-name`**, **`react-x/no-unnecessary-use-prefix`**, **`react-x/no-string-style-prop`**: Fixed missing or incorrect presets in rule documentation (#1826). ### ๐Ÿ“ Documentation [#-documentation-22] * **`naming-convention`**: Expanded examples and annotated Ok cases for `context-name`, `id-name`, and `ref-name` rules (#1819). * Refactored `MyComponent` examples to `Button` component in custom rules of props and function component definition recipes (#1823). * Added `azat-io` eslint-config to the community presets list. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-44] * **`jsx`**: Consolidated whitespace child predicates and added `isEmptyStringExpression` to the public API (#1820). * Added preset verification to `check-docs.ts` (#1822). * Added `AGENTS.md` guide for AI coding agents (#1824). * Normalized local package metadata in `.pkgs/*`. * Bumped `vite` to `^8.0.15` and `ansis` to `^4.3.1` across workspace packages. ### New Contributors [#new-contributors-1] * **Kenton Jacobsen** (@brokentone) made their first contribution in #1825. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.9...v5.8.10](https://github.com/Rel1cx/eslint-react/compare/v5.8.9...v5.8.10) ## v5.8.9 (2026-06-01) [#v589-2026-06-01] ### ๐Ÿž Fixes [#-fixes-26] * **`react-x/no-direct-mutation-state`**: Detect nested state mutations and member expressions in assignment expressions (#1818). ### ๐Ÿ“ Documentation [#-documentation-23] * Updated contributing guide and monorepo structure documentation. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-45] * Removed `.vscode` directories from all examples, added missing `engines.node` to Preact examples, cleaned up redundant `.config/*.ts` from `tsconfig.node.json`, and updated `.gitignore`. * Cleaned up configs and docs. * Patch bumped `eslint`, `tinyglobby`, and `tsdown` across workspace packages; added `@fontsource/iosevka-aile` to the website; reordered CSS imports in `layout.tsx`. * Updated `.sentrux` baseline timestamp. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.8...v5.8.9](https://github.com/Rel1cx/eslint-react/compare/v5.8.8...v5.8.9) ## v5.8.8 (2026-05-31) [#v588-2026-05-31] ### ๐Ÿ“ Documentation [#-documentation-24] * **`kit`**: Added `is.APICall` callout to the Kit documentation (#1813). * **`jsx`**: Updated `getChildren` and `hasChildren` API documentation to reflect empty string children behavior. * Reworked status emoji indicators across docs and examples (#1816). * Added โ„ž prefix to recipe titles and cleaned up See Also sections. * Removed the `custom-rules-of-children` recipe and cross-linked the remaining recipes. * Added redirects for moved rule documentation. * Cleaned up the "Community Maintained Presets that use ESLint React" documentation page. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-46] * **`react-x/no-misused-capture-owner-stack`**: Added edge-case tests for `captureOwnerStack` (#1813). * Updated fonts and dropped the `data-theme` attribute. * Updated theme configuration (#1815). * Aligned the `tsdown` version in `@local/configs`. * Enabled `trustPolicy: "no-downgrade"` and added `minimumReleaseAge: 1440` (1 day). * Bumped `eslint` to `10.4.1` across workspace packages. * Bumped `pnpm` to `11.5.0` and refreshed the lockfile. * Bumped `fumadocs` packages and `tinyexec`. * Bumped `eslint-plugin-package-json` to `1.2.0`. * Updated dprint plugins and reformatted font families in example projects. * Updated Sentrux baseline metrics. * Updated `.gitignore`. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.7...v5.8.8](https://github.com/Rel1cx/eslint-react/compare/v5.8.7...v5.8.8) ## v5.8.7 (2026-05-29) [#v587-2026-05-29] ### ๐Ÿž Fixes [#-fixes-27] * **`react-x/no-create-ref`**: Fixed a false positive where `createRef` calls in non-React classes were reported. The rule now only reports `createRef` calls inside function components or Hooks (#1812). * **`react-x/no-unused-state`**: Removed the "only used in effects" detection so the rule only reports state variables that are defined but never used, reducing false positives (#1808, #1749). * **`jsx`**: Aligned children filtering and `hasChildren` behavior with React source, updating `no-children-prop` and `no-useless-fragment` rules accordingly (#1805). * **Zod compatibility**: Relaxed `zod` peer dependency to support both v3 and v4 (#1810). ### ๐Ÿ“ Documentation [#-documentation-25] * **`react-dom`**, **`react-web-api`**, **`react-x`**: Enriched rule MDX examples with TypeScript snippets from react.dev (#1809). * **`react-dom`**: Added more rule examples to `no-dangerously-set-innerhtml`, `no-find-dom-node`, `no-hydrate`, `no-render`, and `no-render-return-value` documentation (#1804). * **`react-dom`**: Added legitimate `flushSync` use cases to `no-flush-sync` rule documentation (#1803). * Bumped the documented ESLint minimum version to `10.3.0`. * Clarified that the `off` preset disables all rules. * Fixed inaccurate minimum ESLint version and `off` preset description in README. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-47] * **`react-x/no-misused-capture-owner-stack`**: Refactored the `process.env.NODE_ENV` detection helpers to use the shared `core.isAPI` utility (#1812). * **`react-x/no-unused-state`**: Removed incorrect invalid test cases. * **`jsx`**: Added targeted test cases for empty string children behavior in `no-children-prop-with-children` and `no-useless-fragment` rules (#1806). * Removed `eslint-plugin-function` and bumped website dependencies (#1811). * Flattened `scripts/lib` into the `scripts` root. * Updated `.textlintrc.json`. * Updated dprint plugins and tidied scripts. * Removed `enriching-rule-examples-from-react-dev.md` from main branch. * Updated Sentrux baseline metrics. * Updated per-rule CHANGELOGs for `no-useless-fragment`, `no-children-prop`, and `no-children-prop-with-children` (#1805). * Bumped dependencies: * `@takumi-rs/image-response` to `^1.6.0` * `dompurify` to `3.4.6` * `fumadocs-mdx` and updated pnpm lockfile * `tsdown` to `0.22.1` * dprint plugins (`g-plane/markup_fmt` and `markdown`) **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.6...v5.8.7](https://github.com/Rel1cx/eslint-react/compare/v5.8.6...v5.8.7) ## v5.8.6 (2026-05-27) [#v586-2026-05-27] ### ๐Ÿ“ Documentation [#-documentation-26] * Improved `react-x/context-name` rule description accuracy. * Removed broken Further Reading links across rule documentation. * Reordered Further Reading links by relevance in `react-x`, `react-dom`, and `react-web-api` rule documentation. * Updated `rule-implementation-patterns-term-based.md` documentation. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-48] * **`ast`**: Replaced `isLiteral` with `isStringLiteral` in `Check` utilities (#1798). * Bumped dependencies across workspace packages: * `@typescript-eslint` to `^8.60.0` * `eslint-plugin-jsdoc` to `63.0.0` * `fumadocs` patch versions * `nx` to `^22.7.4` * `pnpm` and lockfile updates **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.5...v5.8.6](https://github.com/Rel1cx/eslint-react/compare/v5.8.5...v5.8.6) ## v5.8.5 (2026-05-24) [#v585-2026-05-24] ### ๐Ÿ“ Documentation [#-documentation-27] * Added rule implementation patterns guide (`docs/rule-implementation-patterns.md`) and term-based rule patterns guide (`docs/rule-implementation-patterns-term-based.md`). * Lowered minimum TypeScript version requirement from `5.1.0` to `5.0.0` across README and documentation. * Fixed textlint war-metaphor warnings and refined `.textlintrc.json` patterns. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-49] * Adjusted formatting across configuration and script files (#1795). * Fixed a typo in the CI test workflow step. * Added regression tests for oxc issues compatibility verification (#1796). * Bumped dependencies across workspace packages: * `@effect/language-service` to `^0.86.2` * `@takumi-rs/image-response` to `^1.3.0` * `@tsconfig/vite-react` to `^8.0.6` * `@types/node` to `^25.9.1` * `@types/react` to `^19.2.15` * `eslint-plugin-package-json` to `^1.1.0` * `fumadocs-core` to `^16.9.0` * `fumadocs-mdx` to `^15.0.7` * `fumadocs-ui` to `^16.9.0` * `lru-cache` to `11.5.0` * `nx` to `^22.7.3` * `postcss` to `^8.5.15` * `vite` to `^8.0.14` * `vitest` to `^4.1.7` * `pnpm` to `11.2.1` **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.4...v5.8.5](https://github.com/Rel1cx/eslint-react/compare/v5.8.4...v5.8.5) ## v5.8.4 (2026-05-22) [#v584-2026-05-22] ### ๐Ÿ“ Documentation [#-documentation-28] * Restructured the FAQ page from an accordion layout to standard headings for better SEO, accessibility, and direct anchor linking. * Replaced the homepage `Hint` popover with a direct link to the FAQ anchor explaining the project's human/LLM collaboration policy. * Added a new **"What does 90% human-written mean?"** section to the FAQ. * Updated documentation for `isClassComponent` and `JsxConfig`. * Removed outdated documentation files. ### ๐Ÿ—๏ธ Internal [#๏ธ-internal-50] * **`core`**: Simplified `isClassComponent` by removing the `context` parameter and replacing `isClassComponentLoose` with the simplified function. * **`eslint-plugin-react-x`**: Removed unnecessary optional chaining across multiple rules (`immutability`, `no-unused-state`, `purity`, `refs`, `set-state-in-effect`, `static-components`, `use-memo`, etc.) and expanded test coverage for edge cases (#1792). * Added automated GitHub Release workflow and fixed `actions/setup-node` cache parameter error. * Added null-safety boundary tests for rules affected by PR #1792 (#1794). * Bumped dependencies across workspace packages: `@takumi-rs/image-response` to 1.2.1, `fumadocs-mdx` to 15.0.6, `import-integrity-lint` to 1.1.1, `preact` to 10.29.2, `tsx` to 4.22.1, `@typescript-eslint` to `^8.59.4`, `@types/node` to `^25.9.0`, `dompurify` to `^3.4.5`, `pnpm` to `11.1.3`, `textlint` to 15.7.1, and dprint TypeScript plugin to 0.96.1. * Cleaned up stray empty string in `tsl.config.ts`. * Cleaned up type and lint errors across the workspace (#1793). * Downgraded TypeScript override in `pnpm-workspace.yaml` from `^6.0.3` to `5.9.3`. * Fixed zizmor security audit findings in release workflow and moved ignore comments inline, removing `.github/zizmor.yml`. * Removed `scripts/verify-lockfile.ts`, `scripts/verify-devtools.ts`, and all references to them. * Reordered handler functions in `react-jsx/no-children-prop` (no logic change). * Updated baseline metrics and compacted tsconfig. **Full Changelog**: [https://github.com/Rel1cx/eslint-react/compare/v5.8.3...v5.8.4](https://github.com/Rel1cx/eslint-react/compare/v5.8.3...v5.8.4) ## v5.8.3 (2026-05-20) [#v583-2026-05-20] ### ๐Ÿž Fixes [#-fixes-28] * **`react-dom/no-unknown-property`**: Added React 19 `precedence` and `blocking` attributes to the known property allowlist with version-gated tag checks, preventing false positives on `