Every project these days needs a linter of some sorts. So, let’s set one up for our React/Typescript project!
repository: https://github.com/djamaile/hep-demo
#
Starting upLet’s first generate a simple React project by using create-react-app
. Execute the following command:
npx create-react-app hep-demo --template typescript && cd hep-demo
Start the app and see if everything is working properly:
yarn start
tip
If you encounter a issue with "babel-jest": "^26.6.0" add a .env file with SKIP_PREFLIGHT_CHECK=true
(echo 'SKIP_PREFLIGHT_CHECK=true' > .env )
#
Installing packagesNow that our app is working we can start by adding the needed packages. For this setup we would need prettier, husky, lint-staged, eslint-config-airbnb and spotify/prettier-config. The last one is optional, you can also create your own prettier config but recently I have been using spotify's config with pleasant results.
To install the packages, execute the following command:
yarn add @spotify/prettier-config @typescript-eslint/parser husky lint-staged prettier -D
We will use the eslint config of airbnb to do that execute the following command:
npx install-peerdeps --dev eslint-config-airbnb
In the root of your project, create a file called .eslintrc.json
and add the following content to it:
{ "extends": [ "airbnb" ], "parser": "@typescript-eslint/parser", "env": { "browser": true, "commonjs": true, "es6": true, "jest": true, "node": true }, "rules": { "no-console": "off", "import/prefer-default-export": "off", "@typescript-eslint/camelcase": ["off"], "camelcase": ["off"], "react/jsx-props-no-spreading": ["off"], "jsx-a11y/no-static-element-interactions": "off", "react/prop-types": ["off"], "jsx-a11y/href-no-hash": ["off"], "jsx-a11y/click-events-have-key-events": ["off"], "import/no-unresolved": ["off"], "import/extensions": 0, "no-use-before-define": "off", "react/jsx-uses-react": "off", "react/react-in-jsx-scope": "off", "react/jsx-filename-extension": [ "warn", { "extensions": [".js", ".jsx", ".tsx", ".ts"] } ], "max-len": [ "warn", { "code": 100, "tabWidth": 2, "comments": 80, "ignoreComments": false, "ignoreTrailingComments": true, "ignoreUrls": true, "ignoreStrings": true, "ignoreTemplateLiterals": true, "ignoreRegExpLiterals": true } ] }}
You, of course, don’t have to use the same rules as mine. Play with it and see what fits you the best!
#
Configure package jsonOnce the packages are installed, we can make some changes in our package.json. Let’s first start with some handy scripts:
"scripts": { ... "prettier:check": "prettier --check .", "prettier:write": "prettier --write .", "prepare": "husky install"}
The prettier commands are there to check your code and the prepare script we will use in a bit to set up husky with a pre-commit hook.
But first in your package.json
down below you can set prettier to @spotify/prettier-config
and under that you can specify the lint-staged
section.
"prettier": "@spotify/prettier-config","lint-staged": { "*.{js,jsx,ts,tsx}": [ "eslint --fix", "prettier --write" ], "*.{json,md}": [ "prettier --write" ]}
lint-staged
will execute those commands on files that are ready to be committed. Basically, it will run its specified linter on all staged git files. But before that is possible, we need to make sure that husky triggers lint-staged
.
In the root of your project run:
yarn prepare
Which will create the .husky
folder in your project and after we can install a pre-commit hook:
npx husky add .husky/pre-commit "yarn lint-staged"
This will create a pre-commit hook in the .husky
folder. If we inspect the contents of the file you can see that it will run yarn lint-staged
.
#
Ignore filesBefore we can test if it works, we should also create .ignore files for prettier and eslint. We don't want to end up scanning the node_modules
folder! Create the files:
touch .eslintignoretouch .prettierignore
In both of the files you can add the same folders to ignore:
**/node_modules/****/build/****/dist/****/.git/****/public/**
#
TestingNow we can actually test if our setup works! First, we’ll need to set up a git for our project:
git initgit add .git commit -m "first commit"
After you try to commit, you can see husky in action. It will execute yarn lint-staged
which in turns calls prettier and eslint for our git staged files.
To see if it works on new stuff, let’s create a file called Button.tsx
in the src directory. Once you have done that, add the following code to it:
import React from 'react';
interface Props { size: string;}
export const Button: React.FC<Props> = ({size}) => { size = 'big'; return <button>{size}</button>;};
So, this piece of code is wrong but let eslint tell us why. Add the file and try to commit it:
git add .git commit -m "feat: add button component"
If eslint is working well you should receive this error:
error Assignment to function parameter 'size' no-param-reassign
error Missing an explicit type attribute for button react/button-has-type
Seems like we have some errors, so let’s fix them before committing our button. Overwrite Button.tsx
with the fixed code:
import React from 'react';
interface Props { size: string;}
export const Button: React.FC<Props> = ({ size }) => { const rightSize = size ? 'big' : 'small'; return <button type="button">{rightSize}</button>;};
The code now looks good, but the styling might look a bit off. But that is okay. We are going to let prettier handle that. Let’s try again to add and commit our Button component.
git add .git commit -m "feat: add button component"
Now we should be greeted by green light and that our component is commited! In addition, if we look at the button component we can see that prettier has rewritten our component, to make it look nicer!
import React from 'react';
interface Props { size: string;}
export const Button: React.FC<Props> = ({ size }) => { const rightSize = size ? 'big' : 'small'; return <button type="button">{rightSize}</button>;};