ESLint plugin that enforces the Rules of Hooks for React applications with additional React Compiler rules
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
This document covers all configuration options and presets available in eslint-plugin-react-hooks, including setup for different ESLint versions and custom rule configurations.
The plugin provides four pre-configured setups for different ESLint versions and configuration formats.
interface PluginConfigs {
'recommended': LegacyConfig; // Original legacy config
'recommended-legacy': LegacyConfig; // Explicit legacy config
'recommended-latest': FlatConfig[]; // Flat config for ESLint 5.2.0
'flat/recommended': FlatConfig[]; // Flat config for ESLint 6.0.0+
}For ESLint versions that use .eslintrc configuration files.
Original configuration for older versions:
{
"extends": [
"plugin:react-hooks/recommended"
]
}Explicit legacy configuration for newer versions with legacy support:
// Actual configuration from src/index.ts
const ruleConfigs = {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// React Compiler rules (automatically mapped from recommendedRules with severity)
'react-hooks/component-hook-factories': 'error',
'react-hooks/config': 'error',
'react-hooks/error-boundaries': 'error',
'react-hooks/gating': 'error',
'react-hooks/globals': 'error',
'react-hooks/immutability': 'error',
'react-hooks/incompatible-library': 'warn',
'react-hooks/no-unused-directives': 'error',
'react-hooks/preserve-manual-memoization': 'error',
'react-hooks/purity': 'error',
'react-hooks/refs': 'error',
'react-hooks/set-state-in-effect': 'error',
'react-hooks/static-components': 'error',
'react-hooks/unsupported-syntax': 'warn',
'react-hooks/use-memo': 'error',
};
const recommendedLegacyConfig = {
plugins: ['react-hooks'],
rules: ruleConfigs
};Usage:
{
"extends": [
"plugin:react-hooks/recommended-legacy"
]
}For ESLint's modern flat configuration format.
For the first version with flat config support:
const recommendedLatestConfig = [
{
plugins: {
'react-hooks': plugin
},
rules: ruleConfigs // Same rules as legacy config
}
];Usage:
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
files: ["src/**/*.{js,jsx,ts,tsx}"],
plugins: {
'react-hooks': reactHooks,
},
extends: ['react-hooks/recommended-latest'],
},
];For ESLint 6.0.0 and later with full flat config support:
const flatRecommendedConfig = [
{
plugins: {
'react-hooks': plugin
},
rules: ruleConfigs // Same rules as legacy config
}
];Usage:
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
files: ["src/**/*.{js,jsx,ts,tsx}"],
plugins: {
'react-hooks': reactHooks,
},
extends: ['react-hooks/recommended'],
},
];Configure specific rules individually without using presets:
// Legacy format
const customLegacyConfig = {
plugins: ['react-hooks'],
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': ['warn', {
additionalHooks: '(useMyCustomHook|useMyOtherCustomHook)'
}],
'react-hooks/immutability': 'error',
'react-hooks/purity': 'warn'
}
};
// Flat format
const customFlatConfig = [
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': ['warn', {
additionalHooks: '(useMyCustomHook|useMyOtherCustomHook)'
}],
'react-hooks/immutability': 'error',
'react-hooks/purity': 'warn'
}
}
];Apply different rules to different file patterns:
// Flat config with file-specific rules
export default [
{
files: ["src/components/**/*.{js,jsx,ts,tsx}"],
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error', // Stricter for components
'react-hooks/immutability': 'error'
}
},
{
files: ["src/hooks/**/*.{js,ts}"],
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn', // More lenient for custom hooks
'react-hooks/purity': 'error'
}
}
];The exhaustive-deps rule accepts configuration for custom hooks:
interface ExhaustiveDepsOptions {
additionalHooks?: string; // RegExp pattern string
}Examples:
{
"rules": {
"react-hooks/exhaustive-deps": ["warn", {
// Single custom hook
"additionalHooks": "useMyCustomHook"
}]
}
}
{
"rules": {
"react-hooks/exhaustive-deps": ["warn", {
// Multiple custom hooks
"additionalHooks": "(useMyCustomHook|useMyOtherCustomHook|useThirdHook)"
}]
}
}
{
"rules": {
"react-hooks/exhaustive-deps": ["warn", {
// Pattern matching for hook families
"additionalHooks": "use[A-Z].*Effect"
}]
}
}Most React Compiler rules don't accept additional configuration, but some do:
{
"rules": {
// Example compiler rule configurations
"react-hooks/config": "error",
"react-hooks/gating": ["warn", { /* compiler-specific options */ }],
"react-hooks/immutability": "error",
"react-hooks/no-unused-directives": "warn"
}
}export default [
{
files: ["src/**/*.{js,jsx,ts,tsx}"],
languageOptions: {
globals: {
...globals.browser
}
},
plugins: { 'react-hooks': reactHooks },
extends: ['react-hooks/recommended']
},
{
files: ["scripts/**/*.js", "*.config.js"],
languageOptions: {
globals: {
...globals.node
}
},
plugins: { 'react-hooks': reactHooks },
rules: {
// Only basic rules for non-React files
'react-hooks/rules-of-hooks': 'off',
'react-hooks/exhaustive-deps': 'off'
}
}
];import reactHooks from 'eslint-plugin-react-hooks';
import tseslint from '@typescript-eslint/eslint-plugin';
export default [
{
files: ["**/*.{ts,tsx}"],
plugins: {
'react-hooks': reactHooks,
'@typescript-eslint': tseslint
},
extends: [
'react-hooks/recommended',
'@typescript-eslint/recommended'
],
rules: {
// Enhanced rules for TypeScript
'react-hooks/exhaustive-deps': 'error',
'react-hooks/immutability': 'error'
}
}
];Migrating from .eslintrc to flat config:
// Old .eslintrc.js
module.exports = {
extends: ['plugin:react-hooks/recommended'],
rules: {
'react-hooks/exhaustive-deps': ['warn', {
additionalHooks: 'useMyHook'
}]
}
};
// New eslint.config.js
import reactHooks from 'eslint-plugin-react-hooks';
export default [
{
plugins: { 'react-hooks': reactHooks },
extends: ['react-hooks/recommended'],
rules: {
'react-hooks/exhaustive-deps': ['warn', {
additionalHooks: 'useMyHook'
}]
}
}
];// For ESLint < 9.0.0 (legacy support)
{
"extends": ["plugin:react-hooks/recommended-legacy"]
}
// For ESLint 5.2.0 (first flat config support)
import reactHooks from 'eslint-plugin-react-hooks';
export default [...reactHooks.configs['recommended-latest']];
// For ESLint >= 6.0.0 (full flat config)
import reactHooks from 'eslint-plugin-react-hooks';
export default [...reactHooks.configs['flat/recommended']];// Configuration type definitions
interface LegacyConfig {
plugins: string[];
rules: Record<string, ESLintRuleSeverity>;
}
interface FlatConfig {
files?: string[];
plugins: Record<string, ESLintPlugin>;
rules: Record<string, ESLintRuleSeverity>;
languageOptions?: {
globals?: Record<string, boolean>;
parser?: any;
parserOptions?: any;
};
}
type ESLintRuleSeverity =
| 'off' | 0
| 'warn' | 1
| 'error' | 2
| [ESLintRuleSeverity, any]; // With options
// Plugin interface
interface ESLintPlugin {
meta: {
name: string;
version?: string;
};
rules: Record<string, Rule.RuleModule>;
configs?: Record<string, LegacyConfig | FlatConfig[]>;
}// Enable debug logging for rule execution
export default [
{
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/exhaustive-deps': ['warn', {
additionalHooks: 'useMyHook'
}]
},
settings: {
'react-hooks': {
debug: true
}
}
}
];