Setting Up ESLint for React Native Code
In React Native projects, TypeScript alone doesn't guarantee absence of runtime issues. any spreads throughout the codebase, useEffect with empty dependency array causes bugs with stale closures, components directly mutate parent state via ref. ESLint with the right set of plugins catches these problems statically, before running on device.
Configuration
// eslint.config.mjs (Flat Config, ESLint 9+)
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
import reactPlugin from 'eslint-plugin-react';
import reactHooksPlugin from 'eslint-plugin-react-hooks';
import reactNativePlugin from 'eslint-plugin-react-native';
export default [
js.configs.recommended,
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: { jsx: true },
},
},
plugins: {
'@typescript-eslint': typescript,
react: reactPlugin,
'react-hooks': reactHooksPlugin,
'react-native': reactNativePlugin,
},
rules: {
...typescript.configs['recommended-type-checked'].rules,
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react-native/no-unused-styles': 'error',
'react-native/no-inline-styles': 'warn',
'react-native/no-color-literals': 'warn',
},
},
];
recommended-type-checked requires project: './tsconfig.json' — analysis with type awareness. Slower, but catches what recommended misses: @typescript-eslint/no-floating-promises finds await without try/catch on async functions.
Key Plugins for React Native
-
eslint-plugin-react-hooks— mandatory.exhaustive-depsrule catches 90% ofuseEffectbugs -
eslint-plugin-react-native—no-unused-stylesfindsStyleSheet.createstyles that aren't used anywhere (common leak in large components) -
@typescript-eslintwith type-checking — catchesany, floating promises, unsafe assignments
Prettier + ESLint
npm install --save-dev prettier eslint-config-prettier
eslint-config-prettier disables ESLint rules that conflict with Prettier. In eslint.config.mjs add prettierConfig last — it overrides formatting rules.
.prettierrc:
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"bracketSpacing": true
}
CI Integration
- name: Lint
run: npx eslint . --ext .ts,.tsx --max-warnings 0
- name: Format check
run: npx prettier --check "src/**/*.{ts,tsx}"
--max-warnings 0 — zero warnings allowed. Without this flag ESLint exits with code 0 even with warnings.
Pre-commit via lint-staged
// package.json
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix --max-warnings 0",
"prettier --write"
]
}
}
npx husky add .husky/pre-commit "npx lint-staged"
Timeline: 1 day. Cost is calculated individually.







