ESLint and Prettier setup on VSCode for React dev

How to configure ESLint and Prettier for React development on VSCode
Nov 10, 2020 ・ Updated on Jul 16, 2021

VSCode ESLint code actions on save

I find that I'm setting up ESLint and Prettier way too often nowadays, fumbling through blog posts, stack overflow questions, and official docs every time! πŸ˜‘

So I think it's time that I write about it now and copy-paste it later. Hopefully you'll find it as useful as my future self would. ⭐️

What is linting and why do we need it?

You want to automate the enforcement of a code style guide for your (or your team's) JS code:

  • detect bugs and errors early during dev time πŸ”
  • have them fixed automatically to save effort and mental energy πŸ€–

πŸ“š More on Style Guides: Prettier - Building and enforcing a style guide

You probably don't need this guide if:

You use a framework with ESLint baked in, like

You need this guide if:

You use a bare-bones React setup like

  • Parcel,
  • Next.js
  • or if you ejected from CRA to have more control over settings

Let's see how you can simplify your tooling once and for all! First let's clarify the difference between ESLint and Prettier.

ESLint - a linter

  • linter, aka static code analysis tool
  • identify and report bugs and problematic patterns, like syntax and semantic errors
  • e.g. undefined variables, modification of constants, implicit globals, use of ==, ...
  • extremely configurable - rules to enable/disable, parsers, plugins

Prettier - a formatter

  • formatter, aka prettifier or pretty print tool
  • reprints your code to adhere to formatting rules of a style guide
  • e.g. fixes max line length, whitespace, tabs, spaces, semicolon, comma, ...

In short, ESLint for code quality and Prettier for code formatting

Initial repo

Here's an example React repo using bare-bones Parcel and Babel. Focus on src/Hello.jsx with a lot of formatting errors, which we want to lint.

πŸ“š Parcel is a zero-config bundler as an alternative to Webpack. Babel compiles JSX and other new-gen JS to regular JS that browsers understand.

ESLint - install and config

# install eslint as a dev dep on your project
npm install eslint -D
# initial config
npx eslint --init

eslint --init shows a wizard-like CLI to setup ESLint and install deps at the end.

npx is a tool included with npm to run not-global tools via CLI

Here's the options I picked:

eslint init options for react

Results:

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'plugin:react/recommended',
    'airbnb',
  ],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: [
    'react',
  ],
  rules: {
  },
};

The eslint wizard also installed configs and plugins for us.

package.json

  "devDependencies": {
    // ...
    "eslint": "^7.12.0",
    "eslint-config-airbnb": "^18.2.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-react": "^7.21.5",
    "eslint-plugin-react-hooks": "^4.2.0",
    // ...
  }

πŸ“š Full details on config options here: Configuring ESLint

You can also run eslint CLI manually, e.g. npx eslint --fix src/Hello.jsx for a specific file and npx eslint --fix . to autofix all files, but I want to focus here on integrating with VSCode

VSCode ESLint extension

Install this ESLint extension from VSCode's extension tab

VSCode ESLint extension

We'll do the config for autofix on save later

Watch out for global and local ESLint conflicts

If you have ESLint installed and configured both globally (in your machine) and locally (in your project), you might get this error.

ESLint VSCode local and global conflict error

I suggest to "Allow" local config to be used, to respect individual repo's ESLint rules. Any plugins you use must be installed locally anyways.

ESLint VSCode allow local config

Look ma, lints!

At this point, you should see some lints on Hello.jsx

ESLint lints after config

πŸ’… It would be nice to fix the formatting issues, and for that we need Prettier.

Prettier - install and config

# install prettier to dev deps with exact version
npm install -DE prettier
# create an empty config file, initialize with an empty object
echo {}> .prettierrc.json

Put this initial config:

.prettierrc.json

{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": false,
  "singleQuote": false,
  "trailingComma": "all",
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}

Feel free to customize to your liking. Here's a quick rundown of some options:

  • printWidth: max line length. More than that, Prettier wraps to next line
  • tabWidth: number of spaces per indent
  • semi: semicolons required if true
  • singleQuote: strings must be 'single quoted' if true, "double quoted" if false
  • jsxBracketSameLine and bracketSpacing are IMPORTANT FOR JSX to make component tags more readable

There's only a few options to configure for Prettier, compared to ESLint.

πŸ“š More details at Prettier install and initial config

You can also run prettier CLI manually, e.g. npx prettier --write src/. But we'll focus here on integrating Prettier with ESLint, to have auto-fix on save with VSCode.

Integrating ESLint with Prettier

Run Prettier from ESLint

We'll use an ESLint plugin that runs Prettier as if it was a linter rule.

npm install -D eslint-plugin-prettier
  1. Add prettier plugin to ESLint config as the last item.
  2. In the rules object, add prettier "error" as the last item.

..eslintrc.js

{
  // ...
  "plugins": [
      // ...
      "prettier"
    ],
  "rules": {
    // ...
    "prettier/prettier": "error"
  }
  // ...
}

πŸ“š The other way to integrate is to run both ESLint and Prettier separately. See Prettier ESLint

Eliminate conflicting rules

Fundamentally, it's better to leave code quality to ESLint, and code formatting to Prettier.

But ESLint also have stylistic rules that can conflict with Prettier, like semicolon and quotes rules.

To resolve this, we'll use a config to turn off ESLint rules that conflicts with Prettier.

npm install -D eslint-config-prettier

Add prettier/recommended config rules in ESLint config extends. If it's not yet an array, make it an array and add prettier as the last entry.

.eslintrc.js

{
  // ...
  "extends": [
    // ...
    "plugin:prettier/recommended"
  ]
  // ...
}

This is the Recommended Configuration when using eslint-plugin-prettier plugin and eslint-config-prettier config.

πŸ€– Last piece is to have VSCode automatically fix issue on save.

VSCode - fixing issues automatically on save

Note that since we are using ESLint to run Prettier, we only need the ESLint extension, not the Prettier one.

In VSCode, go to Settings (CTRL + SHIFT + P) then search for "Open Settings JSON". Choose the "Folder" option - Preferences: Open Folder Settings (JSON)

VSCode open folder settings JSON

This creates a .vscode/settings.json in our project folder (if it doesn't exist yet). This settings is scoped only to our project so it won't conflict with the other repos you have.

If you intend to apply this globally on all folders in VSCode, you can use global(user) instead Preferences: Open Settings (JSON).

Add these configs in the object:

settings.json

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

πŸ“š For other options: VSCode ESLint extension

Update: You don't need VSCode's Prettier extension and formatOnSave setting

If you're using ESLint to run Prettier as defined here, make sure to either:

  1. Disable or remove Prettier VSCode extension.
  2. Leave the default or set VSCode's editor.formatOnSave to false. Having codeActionsOnSave set to eslint is the right way to go.

Fixing time!

Go to all the files that has lint errors, and just save them. That simple! πŸ˜†

VSCode ESLint code actions on save

I showed File > Save in the gif, but you can just Ctrl + S as usual

Do the same for hooks.jsx and .eslintrc.js which had some formatting issues as well.

"Unfixable" errors

ESLint can only fix "auto-fixable" problems.

In this example, you'll have to manually add PropTypes and add name to your prop types validation.

Bonus: Hooks linting

If you check hooks.jsx, there are a lot of violations to React Rules of Hooks that are left undetected.

For that, we'll need a ESLint plugin

npm install -D eslint-plugin-react-hooks

Add it to the extends

.eslintrc.js

{
  // ...
  "extends": [
    // ...
    "plugin:react-hooks/recommended"
  ]
  // ...
}

ESLint React Hooks rules lint errors

Now we're getting lint errors for using hooks in functions that are not components or custom hooks. πŸ”

Update: Fix for weird formatting on JSX - use prettier/react

ESLint and Prettier - Weird JSX formatting

I noticed recently that even though auto fix was working fine on functions and hooks, JSX gets weird after a few indentation levels.

But why?

We fixed conflicting rules above above. But since we are using Airbnb preset, which enables eslint-plugin-react behind-the-scenes, this causes some conflicts! 😱

Thus, the "tug of war" between ESLint and Prettier indentation and spacing rules. βš”οΈ

Add prettier/react exclusion

As explained here, it's not enough to use 'prettier' or 'prettier-recommended' under eslint-config-prettier to override the other configs like Airbnb.

We also have to add prettier/react at the end to override those rules.

Update 06/2021: Use prettier instead of prettier/react or any prettier/*

.eslintrc.js

{
  // ...
  "extends": [
    "plugin:react/recommended",
    "airbnb",
    "plugin:prettier/recommended",
    "plugin:react-hooks/recommended",
    // ...
    "prettier", // <--- add this; `prettier/react` for eslint-config-prettier < 8.0.0
  ]
  // ...
}

πŸ“š For additional exclusions and more info eslint-config-prettier installation

Code

Conclusion

Hope this helps 🀞, because this will definitely help me. πŸ€“

Update: I've looked at this guide myself at least 5 times in the last few months.

Worth it! πŸ˜„

Catch you in the next one! Enjoy fixing those errors. ❌ ➑️ βœ…

β¬… Previous post