diff --git a/.pkgs/configs/package.json b/.pkgs/configs/package.json index 359e3d883f..4208372ce0 100644 --- a/.pkgs/configs/package.json +++ b/.pkgs/configs/package.json @@ -24,8 +24,8 @@ "eslint-plugin-de-morgan": "^1.2.1", "eslint-plugin-function": "^0.0.21", "eslint-plugin-jsdoc": "^50.7.1", - "eslint-plugin-perfectionist": "^4.13.0", - "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-perfectionist": "^4.14.0", + "eslint-plugin-regexp": "^2.8.0", "eslint-plugin-unicorn": "^59.0.1", "typescript-eslint": "^8.33.1" } diff --git a/.pkgs/eslint-plugin-local/package.json b/.pkgs/eslint-plugin-local/package.json index 0c5236f54c..4928c8bdd1 100644 --- a/.pkgs/eslint-plugin-local/package.json +++ b/.pkgs/eslint-plugin-local/package.json @@ -34,8 +34,8 @@ "@typescript-eslint/utils": "^8.33.1", "eslint-plugin-de-morgan": "^1.2.1", "eslint-plugin-jsdoc": "^50.7.1", - "eslint-plugin-perfectionist": "^4.13.0", - "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-perfectionist": "^4.14.0", + "eslint-plugin-regexp": "^2.8.0", "eslint-plugin-unicorn": "^59.0.1", "string-ts": "^2.2.1", "ts-pattern": "^5.7.1" diff --git a/apps/website/package.json b/apps/website/package.json index 3cd1b81c54..8a698ae2d0 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -20,7 +20,7 @@ "fumadocs-twoslash": "3.1.3", "fumadocs-typescript": "4.0.5", "fumadocs-ui": "15.5.0", - "lucide-react": "^0.511.0", + "lucide-react": "^0.512.0", "next": "^15.3.3", "next-view-transitions": "^0.3.4", "react": "^19.1.0", @@ -52,7 +52,7 @@ "eslint": "^9.28.0", "eslint-plugin-de-morgan": "^1.2.1", "eslint-plugin-import-x": "^4.15.0", - "eslint-plugin-perfectionist": "^4.13.0", + "eslint-plugin-perfectionist": "^4.14.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-unicorn": "^59.0.1", diff --git a/examples/vite-react-dom-js-with-babel-eslint-parser-app/package.json b/examples/vite-react-dom-js-with-babel-eslint-parser-app/package.json index ea1c5684c6..536ee87350 100644 --- a/examples/vite-react-dom-js-with-babel-eslint-parser-app/package.json +++ b/examples/vite-react-dom-js-with-babel-eslint-parser-app/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "@babel/core": "^7.27.4", - "@babel/eslint-parser": "^7.27.1", + "@babel/eslint-parser": "^7.27.5", "@babel/preset-env": "^7.27.2", "@babel/preset-react": "^7.27.1", "@eslint/config-inspector": "^1.0.2", diff --git a/package.json b/package.json index a864c3b865..388a4b7e48 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "typedoc-plugin-mdn-links": "^5.0.2", "typescript": "^5.8.3", "typescript-eslint": "^8.33.1", - "vitest": "^3.2.0" + "vitest": "^3.2.1" }, "packageManager": "pnpm@10.11.1", "engines": { @@ -112,7 +112,7 @@ "@types/react-dom": "^19.1.5", "cross-spawn": "^7.0.6", "esbuild": "^0.25.5", - "lucide-react": "^0.511.0", + "lucide-react": "^0.512.0", "next": "^15.3.3", "react": "^19.1.0", "react-dom": "^19.1.0", diff --git a/packages/plugins/eslint-plugin-react-hooks-extra/src/plugin.ts b/packages/plugins/eslint-plugin-react-hooks-extra/src/plugin.ts index 06c19260f2..ed0a909947 100644 --- a/packages/plugins/eslint-plugin-react-hooks-extra/src/plugin.ts +++ b/packages/plugins/eslint-plugin-react-hooks-extra/src/plugin.ts @@ -1,4 +1,10 @@ import { name, version } from "../package.json"; + +import noUnnecessaryUseCallback from "./rules-removed/no-unnecessary-use-callback"; +import noUnnecessaryUseMemo from "./rules-removed/no-unnecessary-use-memo"; +import noUnnecessaryUsePrefix from "./rules-removed/no-unnecessary-use-prefix"; +import preferUseStateLazyInitialization from "./rules-removed/prefer-use-state-lazy-initialization"; + import noDirectSetStateInUseEffect from "./rules/no-direct-set-state-in-use-effect"; import noDirectSetStateInUseLayoutEffect from "./rules/no-direct-set-state-in-use-layout-effect"; @@ -10,5 +16,26 @@ export const plugin = { rules: { "no-direct-set-state-in-use-effect": noDirectSetStateInUseEffect, "no-direct-set-state-in-use-layout-effect": noDirectSetStateInUseLayoutEffect, + + /** + * @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead. + * @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-callback + */ + "no-unnecessary-use-callback": noUnnecessaryUseCallback, + /** + * @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead. + * @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-memo + */ + "no-unnecessary-use-memo": noUnnecessaryUseMemo, + /** + * @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead. + * @see https://next.eslint-react.xyz/docs/rules/no-unnecessary-use-prefix + */ + "no-unnecessary-use-prefix": noUnnecessaryUsePrefix, + /** + * @deprecated Use the same rule from `eslint-plugin-react-x` or `@eslint-react/eslint-plugin` instead. + * @see https://next.eslint-react.xyz/docs/rules/prefer-use-state-lazy-initialization + */ + "prefer-use-state-lazy-initialization": preferUseStateLazyInitialization, }, } as const; diff --git a/packages/plugins/eslint-plugin-react-hooks-extra/src/rules-removed/no-unnecessary-use-callback.md b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules-removed/no-unnecessary-use-callback.md new file mode 100644 index 0000000000..5dc4e40d25 --- /dev/null +++ b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules-removed/no-unnecessary-use-callback.md @@ -0,0 +1,67 @@ +--- +title: no-unnecessary-use-callback +--- + +**Full Name in `eslint-plugin-react-hooks-extra`** + +```sh copy +react-hooks-extra/no-unnecessary-use-callback +``` + +**Full Name in `@eslint-react/eslint-plugin`** + +```sh copy +@eslint-react/hooks-extra/no-unnecessary-use-callback +``` + +**Features** + +`🧪` + +## Description + +Disallow unnecessary usage of `useCallback`. + +React Hooks `useCallback` has empty dependencies array like what's in the examples, are unnecessary. The hook can be removed and it's value can be created in the component body or hoisted to the outer scope of the component. + +## Examples + +### Failing + +```tsx +import React, { useCallback } from "react"; + +function MyComponent() { + const onClick = useCallback(() => { + console.log("clicked"); + }, []); + + return