window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster already exists') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Javascript Tools in Action - The Codest
The Codest
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Industries
    • Fintech & Banking
    • E-commerce
    • Adtech
    • Healthtech
    • Manufacturing
    • Logistics
    • Automotive
    • IOT
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
Back arrow GO BACK
2022-09-12
Software Development

Javascript Tools in Action

The Codest

Reda Salmi

React Developer

Discover some retrieving JavaScript tools to level up your programming game. Learn more about ESLint, Prettier and Husky!

It’s awesome to see where Javascript is these days and how much it has evolved sinceES2015, the days of var and $(.submitBtn) are far away behind us. As javascript keeps
evolving, the tools (formatter, linter, bundler) around it keeps getting better, we are going to see in this article how ESLint (linter), Prettier (formatter) and Husky (Git hooks) can improve your developer experience and have a great impact on your application. For the sake of this article we are going to use a React app, but keep in mind that these tools can be used with any Javascript/Node application. We’ll start things by generating a React project using vite with these steps:

npm create vite@latest
Project name: js-tools
Select a framework: react
Select a variant: react
cd js-tools
npm install

ESLint for Code Quality

ESLint is a tool that helps you find and fix problems in your JavaScript code. To add it to our
app we’ll follow these steps:

cd js-tools
npm init @eslint/config
# we'll need to answer these questions to initialize the config
How would you like to use ESLint? To check syntax and find problems
What type of modules does your project use? JavaScript modules (import/export)
Which framework does your project use? React
Does your project use TypeScript? No
Where does your code run? Browser
What format do you want your config file to be in? Javascript
Would you like to install them now? Yes
Which package manager do you want to use? npm
# we are going to install additional plugins
npm i --save-dev eslint-plugin-react-hooks eslint-plugin-jsx-a11y

This will create a .eslintrc.cjs file containing our ESLint config in the root of our app, let’s
update the config file with our installed plugins and add a rule:

const error = 2;

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react/jsx-runtime',
    'plugin:react-hooks/recommended',
    'plugin:jsx-a11y/recommended',
  ],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['react'],
  rules: {
    'no-unused-vars': error,
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
  ignorePatterns: ['node_modules', '.eslintrc.cjs', 'dist'],
};

We are using the recommended settings for each plugin and made the no-unused-vars throw an error, an additional step is to add a lint command to our package.json file as follows:

{
  ...,
    "scripts": {
        "dev": "vite",
        "build": "vite build",
        "preview": "vite preview",
        "lint": "eslint --ext js,jsx ."
    },
  ...
}

Now that our ESLint setup is ready, we are going to update our app to do some testing and see
how it works. The first thing to do is to update the App.jsx file inside the src folder, this component contains an image, a basic video player and a button that toggles the video player
play/pause states when clicked:

import { useEffect, useRef, useState } from 'react';

export default function () {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const heading = 'Hello ESLint + Prettier + Husky';

  useEffect(() => {
    if (!isPlaying) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, []);

  const togglePlay = () => setIsPlaying(!isPlaying);

  return (
    <div>
      <button type="button" onClick={togglePlay}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>

      <div>
        <video
          loop
          playsInline
          ref={videoRef}
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
        />
      </div>

      <div>
        <img src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg" />
      </div>
    </div>
  );
}

import { useEffect, useRef, useState } from 'react';

export default function () {
const videoRef = useRef(null);
const [isPlaying, setIsPlaying] = useState(false);
const heading = 'Hello ESLint + Prettier + Husky';

useEffect(() => {
if (!isPlaying) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}, []);

const togglePlay = () => setIsPlaying(!isPlaying);

return (

<div>
    <video
      loop
      playsInline
      ref={videoRef}
      src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
    />
  </div>

  <div>
    <img src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg" />
  </div>
</div>
);
}

Let’s try and see what running the lint command will report about our App.jsx code:

We have 4 errors great or not so great should I say, we’ve just caught multiple type of errors some are related to React, some to a11y, and one is due to the rule that we’ve added to forbid unused variables. What’s great about ESLint is that it catches errors for you and give us an indication on the solution and all the rules are very well documented. So to fix our code we’ll need to:

– Give a name to our component

– Use the `heading` variable or just delete it if it is useless

– Add a `track` tag for captions in the video player

– Add an `alt` attributes with meaningful text to the image element

After applying these fixes running the `lint` command, we receive no errors, our fixed code is as follows:

  import { useEffect, useRef, useState } from 'react';

export default function App() {
const videoRef = useRef(null);
const [isPlaying, setIsPlaying] = useState(false);
const heading = 'Hello ESLint + Prettier + Husky';

useEffect(() => {
if (!isPlaying) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}, [isPlaying]);

const togglePlay = () => setIsPlaying(!isPlaying);

return (

{heading}

<div>
    <video
      loop
      playsInline
      ref={videoRef}
      src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
    >
      <track kind="captions" src="flower-en.vtt" srcLang="en" />
    </video>
  </div>

  <div>
    <img
      alt="Grapefruit slice atop a pile of other slices"
      src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
    />
  </div>
</div>
);
}

It is a little annoying to have to use the lint command before each commit and one could forget to do that, setting up a git hook could be helpful to automate this task and solve this problem and that’s what we are going to talk about in the Husky section.

Prettier for code formatting

Prettier is an opinionated code formatter that supports many languages and integrates with many code editors. Let’s add prettier to our app:

npm install --save-dev --save-exact prettier

We’ll need to create two files at the root of our app a .prettierignore file to ignore files or folders we don’t want to format:

node_modules/
dist/
public/

And a .prettierrc.json file that will contain our prettier config:

{
"arrowParens": "always",
"bracketSameLine": false,
"bracketSpacing": true,
"endOfLine": "lf",
"embeddedLanguageFormatting": "auto",
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxSingleQuote": false,
"printWidth": 80,
"proseWrap": "always",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": true
}

Prettier config is customizable, you can play with the prettier playground to find the settings that fits you the most. An additional step to make prettier work well with ESLint is to install an additional ESLint plugin:

npm i --save-dev eslint-config-prettier

We’ll also need to update the .eslintrc.cjs file by adding prettier to the extends array, we need to make sure to put it in the last position to override other configs:

const error = 2;

module.exports = {
...,
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'prettier',
],
...

Running prettier is easy and straightforward, one way is to run the npx prettier --write . command that will format all your app code, a second way is to use it from your editor, this will get the most from Prettier, either via a keyboard shortcut or automatically whenever you save a file. When a line has gotten so long while coding that it won’t fit on your screen, just hit a key and watch it magically be wrapped into multiple lines! Or when you paste some code and the indentation gets all messed up, let Prettier fix it up for you without leaving your editor.

But still, what if one of the developers uses an editor that doesn’t support prettier and forgets to use the prettier command, there is a way to fix this problem and that’s the subject of the Husky section below.

Husky for Git hooks

Husky helps you setup git hooks to lint your commit messages, run tests, lint code, etc… when you commit or push. We are going to use it along lint-staged to automate the code linting and formatting before committing the code.

npx husky-init && npm install
npm i --save-dev lint-staged

This will create a .husky folder with a pre-commit file. Next step is to update the package.json file to setup lint-staged command and tell it to format any changed file in the current commit:

{
...,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint --ext js,jsx .",
"prepare": "husky install"
},
"lint-staged": {
"**/*.+(js|jsx|json|css)": "prettier --write --ignore-unknown"
},
...
}

Last step is to update the pre-commit file to setup our hook to run the lint command on all the app and format changed files with the lint-staged command:

!/usr/bin/env sh

. "$(dirname -- "$0")/_/husky.sh"

npm run lint
npx lint-staged
```

Let's do some refactoring to our app to see how all of this works, we are going to create a VideoPlayer.jsx component and use it in App.jsx:

```javascript
import { useEffect, useRef } from 'react';

export default function VideoPlayer({ isPlaying, videoSrc, trackSrc }) {
const videoRef = useRef(null);

useEffect(() => {
if (!isPlaying) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}, [isPlaying]);

return (

);
}
import { useState } from 'react';
import VideoPlayer from './VideoPlayer';

export default function App() {
const [isPlaying, setIsPlaying] = useState(false);
const heading = 'Hello ESLint + Prettier + Husky';

const togglePlay = () => setIsPlaying(!isPlaying);

return (
 
{heading}
 <div>
    <VideoPlayer
      isPlaying={isPlaying}
      trackSrc="flower-en.vtt"
      videoSrc="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
    />
  </div>

  <div>
    <img
      alt="Grapefruit slice atop a pile of other slices"
      src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
    />
  </div>
</div>
);
}


Now that we are happy with our code, let’s commit our changes and see how it goes.

husky code commit error

Errors again this time it is yelling because of missing props validation and as you can see our commit wasn’t successful. Let’s fix this, by first installing PropTypes npm i prop-types and updating the VideoPlayer component:

import { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';

export default function VideoPlayer({ isPlaying, videoSrc, trackSrc }) {
const videoRef = useRef(null);

useEffect(() => {
if (!isPlaying) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}, [isPlaying]);

return (

);
}

VideoPlayer.propTypes = {
isPlaying: PropTypes.bool.isRequired,
videoSrc: PropTypes.string.isRequired,
trackSrc: PropTypes.string.isRequired,
};

After fixing those errors our commit was successful after running the linting and code formatting commands. As you can see with Husky we basically automated linting and formatting with this pre-commit hook and this will avoid any unwanted code in our code base and solve problems like editors incompatibilities and forgetting to run those commands.

sucessful code commit

Summary

ESLint, Prettier and Husky are great tools that help us maintain our code. Combined together they provide us with a great developer experience and make maintaining our code easier.

We’ve talked about linting and formatting in this article, but the tools available and possibilities are much wider you could setup some tests to run on a pre-commit hook or if you use Typescript, adding a type checking command with Husky to skip any untyped code in your app.

career at the codest

Read more:

Pros and Cons of Vue

How to Kill a Project with Bad Coding Practises

React: Tips and Tricks

Related articles

Software Development

Build Future-Proof Web Apps: Insights from The Codest’s Expert Team

Discover how The Codest excels in creating scalable, interactive web applications with cutting-edge technologies, delivering seamless user experiences across all platforms. Learn how our expertise drives digital transformation and business...

THECODEST
Software Development

Top 10 Latvia-Based Software Development Companies

Learn about Latvia's top software development companies and their innovative solutions in our latest article. Discover how these tech leaders can help elevate your business.

thecodest
Enterprise & Scaleups Solutions

Java Software Development Essentials: A Guide to Outsourcing Successfully

Explore this essential guide on successfully outsourcing Java software development to enhance efficiency, access expertise, and drive project success with The Codest.

thecodest
Software Development

The Ultimate Guide to Outsourcing in Poland

The surge in outsourcing in Poland is driven by economic, educational, and technological advancements, fostering IT growth and a business-friendly climate.

TheCodest
Enterprise & Scaleups Solutions

The Complete Guide to IT Audit Tools and Techniques

IT audits ensure secure, efficient, and compliant systems. Learn more about their importance by reading the full article.

The Codest
Jakub Jakubowicz CTO & Co-Founder

Subscribe to our knowledge base and stay up to date on the expertise from the IT sector.

    About us

    The Codest – International software development company with tech hubs in Poland.

    United Kingdom - Headquarters

    • Office 303B, 182-184 High Street North E6 2JA
      London, England

    Poland - Local Tech Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warsaw, Poland

      The Codest

    • Home
    • About us
    • Services
    • Case Studies
    • Know How
    • Careers
    • Dictionary

      Services

    • It Advisory
    • Software Development
    • Backend Development
    • Frontend Development
    • Staff Augmentation
    • Backend Developers
    • Cloud Engineers
    • Data Engineers
    • Other
    • QA Engineers

      Resources

    • Facts and Myths about Cooperating with External Software Development Partner
    • From the USA to Europe: Why do American startups decide to relocate to Europe
    • Tech Offshore Development Hubs Comparison: Tech Offshore Europe (Poland), ASEAN (Philippines), Eurasia (Turkey)
    • What are the top CTOs and CIOs Challenges?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. All rights reserved.

    en_USEnglish
    de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek en_USEnglish