or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

base-configuration.mdhooks-configuration.mdindex.mdlegacy-configuration.mdmain-configuration.mdrule-modules.mdwhitespace-configuration.md
tile.json

hooks-configuration.mddocs/

React Hooks Configuration

Additional ESLint rules specifically for React Hooks, enforcing Rules of Hooks and exhaustive dependencies for React 16.8+.

Capabilities

Hooks Configuration

Provides React Hooks-specific ESLint rules that must be used alongside the main configuration.

/**
 * React Hooks ESLint configuration
 * Usage: extends: ['airbnb', 'airbnb/hooks']
 */
const hooksConfig = {
  plugins: ['react-hooks'],
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    }
  },
  rules: {
    'react-hooks/rules-of-hooks': 'error',
    'react-hooks/exhaustive-deps': 'error'
  }
};

Usage Examples:

// .eslintrc.js - Complete React setup with hooks
module.exports = {
  extends: ['airbnb', 'airbnb/hooks']
};

// .eslintrc.js - With custom hook rules
module.exports = {
  extends: ['airbnb', 'airbnb/hooks'],
  rules: {
    'react-hooks/exhaustive-deps': 'warn' // Downgrade to warning
  }
};

// .eslintrc.js - TypeScript React with hooks
module.exports = {
  extends: ['airbnb', 'airbnb/hooks'],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true
    }
  }
};

Rules of Hooks Enforcement

Enforces React's Rules of Hooks to ensure hooks are called consistently.

/**
 * Enforces Rules of Hooks
 * - Only call hooks at the top level
 * - Only call hooks from React functions
 */
const rulesOfHooks = {
  'react-hooks/rules-of-hooks': 'error'
};

What this rule catches:

// ❌ Bad - conditional hook call
function Component({ condition }) {
  if (condition) {
    const [state, setState] = useState(0); // Error!
  }
  return <div>...</div>;
}

// ❌ Bad - hook in loop
function Component({ items }) {
  items.forEach(item => {
    const [state, setState] = useState(item); // Error!
  });
  return <div>...</div>;
}

// ✅ Good - hooks at top level
function Component({ condition, items }) {
  const [state, setState] = useState(0);
  const [itemState, setItemState] = useState(items);
  
  if (condition) {
    // Use state here
  }
  
  return <div>...</div>;
}

Exhaustive Dependencies

Ensures that useEffect, useMemo, and useCallback hooks declare all dependencies.

/**
 * Enforces exhaustive dependency arrays
 * - All dependencies must be listed in dependency array
 * - Warns about missing dependencies
 */
const exhaustiveDeps = {
  'react-hooks/exhaustive-deps': 'error'
};

What this rule catches:

// ❌ Bad - missing dependency
function Component({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, []); // Error! Missing userId dependency
  
  return <div>{user?.name}</div>;
}

// ❌ Bad - stale closure
function Component() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + 1); // Error! Using stale count
    }, 1000);
    return () => clearInterval(timer);
  }, []); // Missing count dependency
  
  return <div>{count}</div>;
}

// ✅ Good - complete dependencies
function Component({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]); // Correct dependency
  
  return <div>{user?.name}</div>;
}

// ✅ Good - functional update
function Component() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    const timer = setInterval(() => {
      setCount(prevCount => prevCount + 1); // Functional update
    }, 1000);
    return () => clearInterval(timer);
  }, []); // No dependencies needed
  
  return <div>{count}</div>;
}

Plugin Requirements

The hooks configuration requires the react-hooks plugin:

interface HooksPluginRequirement {
  'eslint-plugin-react-hooks': string; // '^4.3.0'
}

Configuration Structure

interface HooksConfiguration {
  plugins: ['react-hooks'];
  parserOptions: {
    ecmaFeatures: {
      jsx: boolean;
    };
  };
  rules: {
    'react-hooks/rules-of-hooks': 'error';
    'react-hooks/exhaustive-deps': 'error';
  };
}