Created
July 17, 2025 22:15
-
-
Save jon-hotaisle/9dd8078df6abb3e8e7821bbf013b6594 to your computer and use it in GitHub Desktop.
Struggling with eslint flat file configuration for a react/vite project? This one works pretty well for me.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bun add --dev @eslint/js eslint-config-prettier eslint-plugin-import \ | |
// eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-unused-imports \ | |
// eslint eslint-plugin-promise eslint-plugin-react-refresh globals prettier | |
import js from '@eslint/js'; | |
import tseslint from 'typescript-eslint'; | |
import configPrettier from 'eslint-config-prettier'; | |
import pluginImport from 'eslint-plugin-import'; | |
import pluginReact from 'eslint-plugin-react'; | |
import reactHooks from 'eslint-plugin-react-hooks'; | |
import pluginUnusedImports from 'eslint-plugin-unused-imports'; | |
import { globalIgnores } from 'eslint/config'; | |
import pluginPromise from 'eslint-plugin-promise'; | |
import reactRefresh from 'eslint-plugin-react-refresh'; | |
import globals from 'globals'; | |
export default tseslint.config( | |
globalIgnores(['node_modules/', 'dist/', 'example/', '*.d.ts', 'types/', '**/*.d.ts', 'src/routeTree.gen.ts']), | |
js.configs.recommended, | |
...tseslint.configs.recommended, | |
reactHooks.configs['recommended-latest'], | |
reactRefresh.configs.vite, | |
{ | |
files: ['**/*.{ts,tsx}'], | |
plugins: { | |
'@typescript-eslint': tseslint.plugin, | |
'unused-imports': pluginUnusedImports, | |
import: pluginImport, | |
promise: pluginPromise, | |
react: pluginReact, | |
}, | |
languageOptions: { | |
ecmaVersion: 'latest', | |
globals: globals.browser, | |
parserOptions: { | |
projectService: true, | |
tsconfigRootDir: import.meta.dirname, | |
}, | |
}, | |
rules: { | |
// React hooks rules | |
'react-hooks/rules-of-hooks': 'error', | |
'react-hooks/exhaustive-deps': 'error', | |
// React rules | |
'react/react-in-jsx-scope': 'off', | |
'react/jsx-uses-react': 'off', | |
'react/prop-types': 'off', | |
'react/jsx-no-undef': 'error', | |
'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }], | |
'react/no-unknown-property': 'error', | |
'react/self-closing-comp': 'warn', | |
'react/jsx-curly-brace-presence': ['warn', { props: 'never', children: 'never' }], | |
'react/jsx-no-constructed-context-values': 'warn', | |
// TypeScript rules | |
'@typescript-eslint/no-empty-function': 'off', | |
'@typescript-eslint/await-thenable': 'warn', | |
'@typescript-eslint/no-floating-promises': 'warn', | |
'@typescript-eslint/require-await': 'warn', | |
// Unused imports rules | |
'no-unused-vars': 'off', | |
'@typescript-eslint/no-unused-vars': 'off', | |
'unused-imports/no-unused-imports': 'error', | |
'unused-imports/no-unused-vars': [ | |
'warn', | |
{ | |
vars: 'all', | |
varsIgnorePattern: '^_', | |
args: 'after-used', | |
argsIgnorePattern: '^_', | |
}, | |
], | |
// Import rules | |
'import/order': [ | |
'error', | |
{ | |
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], | |
'newlines-between': 'always', | |
alphabetize: { order: 'asc', caseInsensitive: true }, | |
}, | |
], | |
'no-duplicate-imports': 'warn', | |
}, | |
settings: { | |
react: { | |
version: 'detect', | |
runtime: 'automatic', // For React 17+ JSX transform | |
}, | |
}, | |
}, | |
// Apply prettier config last to override formatting rules | |
configPrettier, | |
); | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment