[React] ESLint

2023-01-25 hit count image

Let's see how to use ESLint in React to find errors and bugs by analyzing the source code.

Blog series

This blog post is a series. You can see the other posts on the link below.

Outline

ESLint is the compound language of ES(EcmaScript) + Lint(show error code), and supports to find potential errors or bugs by analyzing the source code.

Int this blog post, I will show you how to configure ESLint and how to use ESLint in the React project with create-react-app.

Prepare proejct

To use ESLint in React, let’s create a new project with create-react-app. If you want to know more details about create-react-app, see the link below.

Execute the command below to create a new React project for ESLint.

npx create-react-app eslint_example --template=typescript

Normally, I use TypeScript with React, so I use --template=typescript option to create the React project.

ESLint installation

To use ESLint in React, we need to install the ESLint library. Execute the command below to install the ESLint library.

# cd eslint_example
npm install eslint --save-dev

ESLint configuration

Next, we need to configure ESLint to use it in React. Execute the command below to start the ESLint configuration.

npx eslint --init

After executing, you can see the question on the screen like the below.

? How would you like to use ESLint? …
  To check syntax only
❯ To check syntax and find problems
  To check syntax, find problems, and enforce code style

Select the option that you want. I selected To check syntax and find problems. And then, you can see the question on the screen like the below.

? What type of modules does your project use? …
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

Basically, React uses import/export, so select the JavaScript modules (import/export) option. Next, you can see the question like the below.

? Which framework does your project use? …
❯ React
  Vue.js
  None of these

We’ll use ESLint on React, so select React. And then, you can see the question like the below.

? Does your project use TypeScript? › No / Yes

I use TypeScript when I develop with React, so I selected Yes. If you don’t use TypeScript, select No here. Next, you can see the screen like the below.

? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node

React will run on Browser, so select Browser. Next, you can see the screen like the below.

? What format do you want your config file to be in? …
❯ JavaScript
  YAML
  JSON

You can save the configuration to various formats of files. I prefer to store it in the JavaScript format, so I select JavaScript here.

eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now with npm? › No / Yes

Lastly, we need to install some libraries for this configuration, so select Yes to install them.

ESLint rules

On the ESLint official site and the TypeScript official page, you can see the ESLint rules that you can configure.

  • ESLint Official site: Rules
  • ESLint Plugin TypeScript: Rules

Check the rules and set them to your project. The configuration below is the rules that I use.

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:storybook/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
    project: './tsconfig.json',
  },
  plugins: ['react', '@typescript-eslint', 'functional', 'import'],
  settings: {
    react: {
      version: 'detect',
    },
  },
  rules: {
    // General
    'no-console': ['error', { allow: ['debug', 'warn', 'error'] }],
    // TypeScript
    '@typescript-eslint/consistent-type-imports': 'error',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-member-accessibility': 'off',
    '@typescript-eslint/indent': 'off',
    '@typescript-eslint/member-delimiter-style': 'off',
    '@typescript-eslint/no-confusing-void-expression': [
      'error',
      {
        ignoreArrowShorthand: true,
        ignoreVoidOperator: true,
      },
    ],
    'no-duplicate-imports': 'off',
    '@typescript-eslint/no-duplicate-imports': 'error',
    '@typescript-eslint/no-implicit-any-catch': 'error',
    'no-invalid-this': 'off',
    '@typescript-eslint/no-invalid-this': 'error',
    '@typescript-eslint/no-invalid-void-type': 'error',
    'no-loop-func': 'off',
    '@typescript-eslint/no-loop-func': 'error',
    'no-loss-of-precision': 'off',
    '@typescript-eslint/no-loss-of-precision': 'error',
    '@typescript-eslint/no-parameter-properties': 'off',
    'no-redeclare': 'off',
    '@typescript-eslint/no-redeclare': 'error',
    'no-shadow': 'off',
    '@typescript-eslint/no-shadow': 'error',
    'no-throw-literal': 'off',
    '@typescript-eslint/no-throw-literal': 'error',
    '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
    '@typescript-eslint/no-unnecessary-condition': 'error',
    '@typescript-eslint/no-unnecessary-type-arguments': 'error',
    'no-unused-expressions': 'off',
    '@typescript-eslint/no-unused-expressions': 'error',
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/no-use-before-define': [
      'error',
      {
        variables: false,
      },
    ],
    '@typescript-eslint/prefer-enum-initializers': 'error',
    '@typescript-eslint/prefer-for-of': 'error',
    '@typescript-eslint/prefer-includes': 'error',
    '@typescript-eslint/prefer-nullish-coalescing': 'error',
    '@typescript-eslint/prefer-optional-chain': 'error',
    '@typescript-eslint/prefer-reduce-type-parameter': 'error',
    '@typescript-eslint/prefer-string-starts-ends-with': 'error',
    '@typescript-eslint/prefer-ts-expect-error': 'error',
    '@typescript-eslint/promise-function-async': 'error',
    'no-return-await': 'off',
    '@typescript-eslint/return-await': 'error',
    '@typescript-eslint/strict-boolean-expressions': 'error',
    '@typescript-eslint/switch-exhaustiveness-check': 'error',
    // React
    'react/jsx-boolean-value': 'warn',
    'react/jsx-curly-brace-presence': 'warn',
    'react/jsx-fragments': 'warn',
    'react/jsx-no-useless-fragment': 'warn',
    'react/jsx-uses-react': 'off',
    'react/prefer-stateless-function': 'warn',
    'react/prop-types': 'off',
    'react/react-in-jsx-scope': 'off',
    // Functional
    'functional/prefer-readonly-type': [
      'error',
      {
        allowLocalMutation: true,
        allowMutableReturnType: true,
        ignoreClass: true,
      },
    ],
    'import/order': [
      'error',
      {
        groups: ['builtin', 'external', 'internal'],
        pathGroups: [
          {
            pattern: '{react,react-dom/**}',
            group: 'external',
            position: 'before',
          },
        ],
        pathGroupsExcludedImportTypes: ['react'],
        'newlines-between': 'always',
        alphabetize: {
          order: 'asc',
          caseInsensitive: true,
        },
      },
    ],
    'react/react-in-jsx-scope': 'off',
    'linebreak-style': ['error', 'unix'],
    eqeqeq: ['error', 'always', { null: 'ignore' }],
    camelcase: ['error', { properties: 'never' }],
    quotes: ['error', 'single', { avoidEscape: true }],
  },
};

For using the rule above, you should install the eslint-plugin-functional library. Execute the command below to install it.

npm install --save-dev eslint-plugin-functional

Check by ESLint

You can check the files follow the ESLint rules, that we’ve defined above, or not by executing the command below.

npx eslint ./src

After executing, you can see the file list which didn’t follow the rules.

/eslint_test/src/App.tsx
  5:1  warning  Missing return type on function  @typescript-eslint/explicit-module-boundary-types

/eslint_test/src/reportWebVitals.ts
  1:1   error    All imports in the declaration are only used as types. Use `import type`  @typescript-eslint/consistent-type-imports
  3:25  warning  Missing return type on function                                           @typescript-eslint/explicit-module-boundary-types

✖ 3 problems (1 error, 2 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

Fix by ESLint

If you execute the command below, you can make the files follow the ESLint rules.

npx eslint --fix ./src

When you execute the command, ESLit will fix the files that it can fix, and if ESLint couldn’t fix, the file list will be shown up like the below.

/eslint_test/src/App.tsx
  5:1  warning  Missing return type on function  @typescript-eslint/explicit-module-boundary-types

/eslint_test/src/reportWebVitals.ts
  3:25  warning  Missing return type on function  @typescript-eslint/explicit-module-boundary-types

If you have the files which ESLint couldn’t fix, open the files and fix them by yourself.

// code ./src/App.tsx
function App(): JSX.Element {
// code ./src/reportWebVitals.tsx
const reportWebVitals = (onPerfEntry?: ReportHandler): void => {

After fixing, when you check it again by executing the command below, you can see there are no error and warning.

npx eslint ./src

Now, we can know all files follow the ESLit well.

Normally, I don’t use the --fix option to fix the issues by ESLin automatically. Because it’s important to know the reason of the wrong code and sometimes, ESLit fixes wrong way.

Configure package.json

You can configure the package.json file like the below to use the check command and the fix command easily.

"scripts": {
  ...
  "lint": "eslint ./src",
  "lint:fix": "eslint --fix ./src"
},

After modifying the package.json file, you can execute ESLint by using the command below.

npm run lint
npm run lint:fix

Completed

Done! we’ve seen how to cnofigure ESLint and how to use ESLint in the React project. From now, please use ESLint to find the potential bugs and erros!

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

App promotion

You can use the applications that are created by this blog writer Deku.
Deku created the applications with Flutter.

If you have interested, please try to download them for free.

Posts