Airbnb's comprehensive ESLint configuration as an extensible shared config for JavaScript and React projects
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Additional ESLint rules specifically for React Hooks, enforcing Rules of Hooks and exhaustive dependencies for React 16.8+.
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
}
}
};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>;
}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>;
}The hooks configuration requires the react-hooks plugin:
interface HooksPluginRequirement {
'eslint-plugin-react-hooks': string; // '^4.3.0'
}interface HooksConfiguration {
plugins: ['react-hooks'];
parserOptions: {
ecmaFeatures: {
jsx: boolean;
};
};
rules: {
'react-hooks/rules-of-hooks': 'error';
'react-hooks/exhaustive-deps': 'error';
};
}Install with Tessl CLI
npx tessl i tessl/npm-eslint-config-airbnb