Enforcing Uniform Code Formatting in React with ESLint, Prettier, and Husky

Maintaining consistent code style and quality is crucial in any React project, especially as your team or codebase grows. This article will guide you through setting up ESLint, Prettier, and Husky for your React + TypeScript project with a minimal and effective configuration to enforce uniform formatting and linting.

Why enforce uniform formatting?

  • Improves readability by applying a consistent style across your codebase
  • Reduces code review friction by avoiding style debates
  • Prevents bugs and errors early via linting
  • Automates formatting to save developer time

Tools overview

  • Prettier: An opinionated code formatter that automatically formats your files.
  • ESLint: A linting tool that catches code errors and enforces coding standards.
  • Husky: A Git hooks manager to run commands like linting and formatting before commits.
  • lint-staged: Runs linters only on staged files for faster, focused checks.

Step 1: Install required dependencies

Run this command in your project root to install all required packages:

npm install --save-dev prettier eslint eslint-config-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin husky lint-staged

This includes:

  • prettier for formatting
  • eslint for core linting functionality
  • @typescript-eslint/parser to let ESLint parse TypeScript syntax (interfaces, types, enums, etc.)
  • @typescript-eslint/eslint-plugin to add TypeScript-specific linting rules and best practices
  • eslint-config-prettier to disable ESLint rules that might conflict with Prettier formatting
  • husky and lint-staged for managing Git pre-commit hooks to run linters and formatters automatically

Step 2: Configure Prettier

Create a .prettierrc file in your project root with the following content:

{
  "semi": true,
  "singleQuote": true,
  "printWidth": 80,
  "trailingComma": "all",
  "endOfLine": "lf"
}

This sets basic formatting rules such as using semicolons, single quotes, and consistent line breaks.

Step 3: Configure ESLint

Create a .eslintrc.json file in the root with this minimal TypeScript-focused config:

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint"],
  "rules": {}
}

This enables recommended ESLint and TypeScript rules while deferring formatting concerns to Prettier.

Step 4: Setup lint-staged and Husky

Add this to your package.json to tell lint-staged what files to check and fix on commit:

"lint-staged": {
  "src/**/*.{js,jsx,ts,tsx}": [
    "eslint --fix",
    "prettier --write"
  ]
}

Initialize Husky and add a pre-commit hook:

npx husky install
npx husky add .husky/pre-commit "npx lint-staged"

This runs ESLint and Prettier on your staged files before each commit, helping keep your codebase clean automatically.

Step 5: (Optional) Configure your editor for format on save

If you use VS Code, install the Prettier and ESLint extensions and add the following to your workspace or user settings to format and fix lint issues on save:

{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

Future enhancements

  • Add React-specific linting rules by installing eslint-plugin-react and eslint-plugin-react-hooks.
  • Integrate stylelint for CSS/Tailwind linting.
  • Add testing lint rules (e.g., for Jest).

Conclusion

With just a few dependencies and configuration files, you can automate and enforce consistent code formatting and linting across your React + TypeScript projects. This saves developer time, reduces errors, and improves collaboration—an essential step toward a professional codebase.