@agathongroup/eslint-config

Agathon's ESLint configuration

Usage no npm install needed!

<script type="module">
  import agathongroupEslintConfig from 'https://cdn.skypack.dev/@agathongroup/eslint-config';
</script>

README

Agathon's ESLint configuration

Table of Contents

Usage

There are three ESLint configurations available for your usage:

  1. Default
  2. React
  3. React-Native

Default Config

The default includes non specific frontend framework rules. This configuration can be used in vanilla JS, Node, or non front-end framework projects.

In your .eslintrc:

1. Install dependencies

yarn add --dev @agathongroup/eslint-config eslint babel-eslint prettier eslint-config-prettier

2. In your .eslintrc:

{
  "extends": "@agathongroup"
}

NOTE: Make sure to specify your environment based on your project

React Config

Includes everything in the default config, plus environment specification and react-specific rules with

1. Install dependencies

yarn add --dev @agathongroup/eslint-config eslint babel-eslint prettier eslint-config-prettier eslint-plugin-react eslint-plugin-jsx-a11y

2. In your .eslintrc:

{
  "extends": "@agathongroup/eslint-config/react"
}

React Native Config

Includes everything in the default config, plus environment specification and react-native specific rules with

1. Install dependencies

yarn add --dev @agathongroup/eslint-config eslint babel-eslint prettier eslint-config-prettier eslint-plugin-react eslint-plugin-react-native

2. In your .eslintrc:

{
  "extends": "@agathongroup/eslint-config/react-native"
}

Specifying Environments

The default configuration does not specify a certain environment as to not make any assumptions about the project. The only default environment specified is es2020. You can see the default settings here.

You can specify individual project environments in the .eslintrc file:

{
  "extends": "@agathongroup",
  "env": {
    "browser": true,
    "node": true
  }
}

View all available environments in the ESLint Docs

Editor Integration & Autoformatting

Once you've installed the config, the following are recommended settings for your editor to lint and fix the code for you.

VS Code

  1. Install the ESLint extension: View → Extensions then search and install ESLint

  2. You may need to reload the editor

  3. In your VS Code user settings Code → Preferences → Settings click the icon with the arrow and paper in the top right corner to modify your settings.json file. Add the following to your settings:

    // Format on save with Prettier rules
    "editor.formatOnSave": true,
    // Tell the ESLint plugin to run on save
    "editor.codeActionsOnSave": { "source.fixAll.eslint": true }
    // An array of language identifiers specify the files to be validated
    "eslint.validate": ["html", "javascript", "javascriptreact"]
    

Sublime Text

  1. Install Package Control
  2. Install ESLint-Formatter
  3. And then allow auto fix on save: Preferences → Package Settings → ESLint Formatter → Settings then add "format_on_save": true to the settings file

Enforced Rules

Our ESLint config extends eslint:recommended which enable rules that relate to possible syntax or logic errors in JavaScript. Rules marked with check marks in the large list of ESLint rules are enforced with eslint:recommended.

The rules listed below are enabled in addition to eslint:recommended.

no-console

Disallow the use of console

Using console.log during development is fine, but you shouldn't use console.log in production code.

In JavaScript that is designed to be executed in the browser, it's considered a best practice to avoid using methods on console. Such messages are considered to be for debugging purposes and therefore not suitable to ship to the client. In general, calls using console should be stripped before being pushed to production.

// bad
console.log('bad');
curly

Require following curly brace conventions

Always wrap the block of code in curly braces when using conditionals.

JavaScript allows the omission of curly braces when a block contains only one statement. However, it is considered by many to be best practice to never omit curly braces around blocks, even when they are optional, because it can lead to bugs and reduces code clarity.

// bad
if (foo) foo++;

while (bar) baz();

if (foo) {
  baz();
} else qux();

// good
if (foo) {
  foo++;
}

while (bar) {
  baz();
}

if (foo) {
  baz();
} else {
  qux();
}
eqeqeq

Require === and !==

Use strict equality or inequality operators.

It is considered good practice to use the type-safe equality operators === and !== instead of their regular counterparts == and !=. The reason for this is that == and != do type coercion which follows the rather obscure Abstract Equality Comparison Algorithm. For instance, the following statements are all considered true:

  • [] == false
  • [] == ![]
  • 3 == 03
// bad
a == b;
foo == true;
bananas != 1;
value == undefined;
typeof foo == 'undefined';
'hello' != 'world';
0 == 0;
true == true;
foo == null;

// good
a === b;
foo === true;
bananas !== 1;
value === undefined;
typeof foo === 'undefined';
'hello' !== 'world';
0 === 0;
true === true;
foo === null;
no-eq-null

Disallow Null Comparisons

Use strict equality/inequality when checking null values.

Comparing to null without a type-checking operator (== or !=), can have unintended results as the comparison will evaluate to true when comparing to not just a null, but also an undefined value.

// bad
if (foo == null) {
  bar();
}

while (qux != null) {
  baz();
}

// good
if (foo === null) {
  bar();
}

while (qux !== null) {
  baz();
}
no-use-before-define

Disallow Early Use

Define the variable or function before using it.

In JavaScript, prior to ES6, variable and function declarations are hoisted to the top of a scope, so it's possible to use identifiers before their formal declarations in code. This can be confusing and some believe it is best to always declare variables and functions before using them. In ES6, block-level bindings (let and const) introduce a "temporal dead zone" where a ReferenceError will be thrown with any attempt to access the variable before its declaration.

// bad
alert(a);
const a = 10;

f();
function f() {}

function g() {
  return b;
}
const b = 1;

// good
let a;
a = 10;
alert(a);

function f() {}
f(1);

const b = 1;
function g() {
  return b;
}
prefer-const

Use const instead of let when a constiable is never reassigned.

If a variable is never reassigned, using the const declaration is better. const declaration tells readers, "this variable is never reassigned," reducing cognitive load and improving maintainability.

// bad

// it's initialized and never reassigned.
let a = 3;
console.log(a);

let a;
a = 0;
console.log(a);

// `i` is redefined (not reassigned) on each loop step.
for (let i in [1, 2, 3]) {
  console.log(i);
}

// `a` is redefined (not reassigned) on each loop step.
for (let a of [1, 2, 3]) {
  console.log(a);
}

// good

// using const.
const a = 0;

// it's never initialized.
let a;
console.log(a);

// it's reassigned after initialized.
let a;
a = 0;
a = 1;
console.log(a);

// it's initialized in a different block from the declaration.
let a;
if (true) {
  a = 0;
}
console.log(a);

// it's initialized at a place that we cannot write a variable declaration.
let a;
if (true) {
  a = 0;
}
console.log(a);

// `i` gets a new binding each iteration
for (const i in [1, 2, 3]) {
  console.log(i);
}

// `a` gets a new binding each iteration
for (const a of [1, 2, 3]) {
  console.log(a);
}
prefer-template

Suggest using template literals instead of string concatenation

Use template literals instead of string concatenation.

// bad
const str = 'Hello,' + name + '!';
const str = 'Time: ' + 12 * 60 * 60 * 1000;

// good
const str = 'Hello World!';
const str = `Hello, ${name}!`;
const str = `Time: ${12 * 60 * 60 * 1000}`;

React Specific Rules

Our ESLint config extends plugin:react/recommended which enable rules that relate to common React and JSX errors. You can view all available react rules in the eslint-plugin-react repo. The following rule is enforced in addition to the recommended configuration.

react/no-unescaped-entities

No unescaped entities

This rule prevents characters that you may have meant as JSX escape characters from being accidentally injected as a text node in JSX statements.

// bad
<MyComponent
  name="name"
  type="string"
  foo="bar">  {/* oops! */}
  x="y">
  Body Text
</MyComponent>

// good
<MyComponent>{'Text'}}</MyComponent>
react/react-in-jsx

DISABLE missing React variable when using JSX

This is rule is turned "off" because we use React as a global variable.

react/prop-types

DISABLE prop types validation

This is rule is turned "off" because prop types are not generally used in our projects.

React Native Specific Rules

You can view all available react native rules in the eslint-plugin-react-native repo. The following rules are enforced:

react-native/no-raw-text

Detect raw text outside of Text component

All strings in React Native should be wrapped with a Text component.

// bad
<View>some text</View>

const text = 'some text';
<View>{`${text}`}</View>

// good
<View><Text>some text</Text></View>
const text = 'some text';
<View><Text>{`${text}`}</Text></View>
react-native/no-single-element-style-arrays

No Single Element Style Arrays are allowed

These cause unnecessary re-renders as each time the array's identity changes.

// bad
<View style={[{height: 10}]} />

// good
<View style={{ height: 10 }} />

Overriding Rules

If you'd like to override any rules, you can add the rules to your .eslintrc file.

{
  "rules": {
    "rule-name-here": "off"
  }
}