Creating a React App from scratch 2022

Kobe
Towards Dev
Published in
8 min readJan 3, 2022

--

If you are a junior I think this guide will help you understand how to create react app from scratch, I’ll dive deep into each item and talk to you about what does it mean and why we need to use it. Don’t use it if you don’t know how it runs, how it operates.

React 2022

Overall this guide is below:

  1. Create React App — Link: Set up a modern react web app by running one command.
  2. TypeScript — Link: TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
  3. ESLint — Link: Find and fix problems in your JS, TS code.
  4. Prettier — Link: code Formatter integrated with Eslint
  5. Unit Test (Jest, React Testing Library, coverage)
  6. Style SCSS & Stylelint (https://stylelint.io/)
  7. Git hooks with Husky and Lint-staged

Step 1: Initialize Your code base with typescript

We use Create React App to initialize a new project https://create-react-app.dev/docs/getting-started#creating-a-typescript-app

npx create-react-app my-app --template typescript
yarn create-react-app my-app --template typescript

Step 2: Update Typescript configuration

At the root folder, the create-react-app script will auto-generate a tsconfig.json file and after that, you can adjust the ts config based on your team, you can refer to this link to get more detail about all `tsconfig` options: https://www.typescriptlang.org/tsconfig

Suggestion: We should use the default configuration recommended by typescript https://github.com/tsconfig/bases#create-react-app-tsconfigjson

npm install --save-dev @tsconfig/create-react-app
yarn add --dev @tsconfig/create-react-app

Add to your tsconfig.json:

The default compilerOptions 01/2022

"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"target": "es5",
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react-jsx",
"moduleResolution": "node",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true
}

However, You can override or add more config in your `config`

{
"extends": "@tsconfig/create-react-app/tsconfig.json",
"compilerOptions": {
"target": "es6",
"baseUrl": "src",
"noUnusedLocals": true,
"noUnusedParameters": true,
"incremental": true
}
}

It means we extend all rules from `@tsconfig/create-react-app/config.json` and have some custom rules based on our team.

Step 3: Setup linter for code quality

What is ESLint?

ESLint statically analyses our code and finds the problems. It is present in most of the editors. ESLint fixes are syntax-aware so you won’t experience errors introduced by traditional find-and-replace algorithms. Write your own rules that work alongside ESLint’s built-in rules. You can customize ESLint to work exactly the way you need it for your project.

What is Prettier?

Prettier is an opinionated code Formatter that is compatible with most languages. It saves a lot of time. It quickly indents our code on save (depends on VSCode/editor settings).

npm install prettier eslint --save-dev
yarn add prettier eslint --dev

npx eslint --init
yarn run eslint --init

npx eslint init Select JavaScript -> React -> TypeScript a .eslintrc will be created at the root of your application

Note: If you’re using React v17, you can safely disable the rule in your eslint configuration file “rules”: { “react/react-in-jsx-scope”: “off” }

Plugin recommended avoiding conflict between Eslint & Prettier:

  • @typescript-eslint/eslint-plugin: Plugin to lint your ts code
  • eslint-config-prettier: Turns off all rules that are unnecessary or might conflict with Prettier.
  • eslint-plugin-prettier: Runs Prettier as an ESLint rule
npm install @typescript-eslint/eslint-plugin eslint-config-prettier eslint-plugin-prettier prettier --save-dev

yarn add @typescript-eslint/eslint-plugin eslint-config-prettier eslint-plugin-prettier prettier --dev

Edit the.eslintrc file and add extends section property in the Eslint config file use the rules recommended from Eslint repo https://github.com/eslint/eslint/blob/main/conf/eslint-recommended.js

"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:prettier/recommended"
],

Create .prettierrc with necessary options

{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"trailingComma": "all",
"bracketSpacing": false,
"arrowParens": "always"
}

!!! Important: In case after running Eslint to check your codebase you can catch the two kinds of errors

1. Parsing error: ‘import’ and ‘export’ may appear only with ‘sourceType: module’
2. Parsing error: Unexpected token module

The problems are we try to run the Eslint on the ts file and the Eslint don’t know exactly what is need to clarify here the ts file need to parse itself to to js file and the Eslint can clarify it so we need to add a parser option to Eslint can understand what should it do https://www.npmjs.com/package/@typescript-eslint/parser

npm i --save-dev typescript @typescript-eslint/parser
yarn add -D typescript @typescript-eslint/parser

An ESLint parser that leverages TypeScript ESTree to allow for ESLint to lint TypeScript source code.

{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"project": "./tsconfig.json",
"sourceType": "module"
},
...
}

Another client recommended for React hooks: https://reactjs.org/docs/hooks-rules.html#eslint-plugin

npm install eslint-plugin-react-hooks --save-dev
yarn add eslint-plugin-react-hooks -D
// Your ESLint configuration
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
}
}

Step 4: Setup and run tests & coverage

Create React App uses Jest as its test runner. To prepare for this integration, we did a major revamp of Jest so if you heard bad things about it years ago, give it another try.

Filename Conventions Jest will look for test files with any of the following popular naming conventions:

Files with .js suffix in __tests__ folders.
Files with .test.js suffix.
Files with .spec.js suffix.

From React team (https://reactjs.org/docs/testing.html) recommended tool is React Testing library

Jest is a JavaScript test runner that lets you access the DOM via jsdom. While jsdom is only an approximation of how the browser works, it is often good enough for testing React components. Jest provides a great iteration speed combined with powerful features like mocking modules and timers so you can have more control over how the code executes. https://jestjs.io/docs/getting-started

React Testing Library is a set of helpers that let you test React components without relying on their implementation details. This approach makes refactoring a breeze and also nudges you towards best practices for accessibility. Although it doesn’t provide a way to “shallowly” render a component without its children, a test runner like Jest lets you do this by mocking. https://github.com/testing-library/react-testing-library

Docs : https://testing-library.com/docs/react-testing-library/intro/ Best practices for this lib : https://kentcdodds.com/blog/common-mistakes-with-react-testing-library

Add React testing libs to project’s devDependencies:

npm install --save-dev @testing-library/react @testing-library/react @testing-library/user-eventyarn add --dev @testing-library/react @testing-library/react @testing-library/user-event

Initializing Test Environment

If your app uses a browser API that you need to mock in your tests or if you need a global setup before running your tests, add a src/setupTests.ts to your project. It will be automatically executed before running your tests.

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;

Add Jest collectCoverageFrom options in the package.json

  "scripts": {
...
"test": "react-scripts test",
"coverage": "npm test -- --coverage --watchAll=false",
...
}
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!<rootDir>/node_modules/",
"!src/index.tsx",
"!src/reportWebVitals.ts",
"!src/serviceWorker.ts",
"!src/serviceWorkerRegistration.ts"
]
},

ESlint for Jest & React Testing Library

The current the ESlint will notify errors warning related to jest test E.g

ESLint: ‘test’ is not defined.(no-undef) ESLint: ‘expect’ is not defined.(no-undef)

The problem the ESlint don’t know what is the test & expect key work comes from. We need to add a plugin to resolve this problem eslint-plugin-jest: https://github.com/jest-community/eslint-plugin-jest

npm install --save-dev eslint-plugin-jest
yarn add --dev eslint-plugin-jest

Open .eslintrc and add jest to the plugins list

{
"plugins": ["jest"]
}

You can also tell ESLint about the environment variables provided by Jest by doing This is included in all configs shared by this plugin, so can be omitted if extending them.

{
"env": {
"jest/globals": true
}
}

Recommended This plugin exports a recommended configuration that enforces good testing practices. To enable this configuration use the extends property in your .eslintrc config file:

{
"extends": ["plugin:jest/recommended"]
}

eslint-plugin-testing-library is an ESLint plugin for Testing Library that helps users to follow best practices and anticipate common mistakes when writing tests.

npm install --save-dev eslint-plugin-testing-library
yarn add --dev eslint-plugin-testing-library

Open .eslintrc and add testing-library to the plugins list

{
"plugins": ["testing-library"]
}

Step 5: Setup Style SCSS & Stylelint

Because we are using create-react-app, just add sass as a dev dependency.

Install Sass

npm install --save-dev sass
yarn add --dev sass

LibSass and Node Sass are deprecated. While they will continue to receive maintenance releases indefinitely, there are no plans to add additional features or compatibility with any new CSS or Sass features. Projects that still use it should move onto Dart Sass.

Then just replace/rename all CSS files and corresponding imports to _.scss instead of _.css

Setup Stylelint

https://github.com/stylelint/stylelint

Stylelint is designed for CSS. However, it can be used with PostCSS syntaxes that: parse CSS-like languages like SCSS, Less and SugarSS extract styles from HTML, JavaScript and Markdown

Linting SCSS

npm install --save-dev stylelint stylelint-config-standard-scss postcss@8yarn add -D stylelint stylelint stylelint-config-standard-scss postcss@8

Note: postcss@8 dependency required https://github.com/stylelint-scss/stylelint-config-standard-scss/issues/5

Create .stylelintrc.json file at the root folder

{
"extends": "stylelint-config-standard-scss",
"rules": {
"max-line-length": 120,
"no-empty-source": null,
"indentation": 2,
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true
}
}

Add new script style-lint to package.json scripts.

"style-lint": "stylelint --config=.stylelintrc.json \"src/**/*.scss\" --formatter verbose",

Step 6: Set Up Git hooks with husky and lint-staged

Helpful npm Packages We will rely on a couple of npm packages that will help us set up git hooks.

The first package is Husky which lets you tie an npm script or CLI command to a git hook in your package.json file. We will only be looking at implementing a pre-commit and pre-push hook, although Husky does support all the git hooks defined in the git documentation.

The second package is lint-staged that you can use to run linting against staged git files only. It’s helpful to run git hooks only on files that you have changed and are trying to commit or push. Running git hooks on all files in a large codebase would be prohibitively slow.

Installing Packages

npm install husky lint-staged --save-dev
yarn add --dev husky lint-staged

We have 5 sections that need to be config together

  • husky — for using git hooks.
  • lint-staged — for running the command before committing .
  • prettier — for formatting the code.
  • eslint — for checking typescript codebase
  • stylelint — for checking style (css, scss) files

All script related below :

{
"style-lint": "stylelint --config=.stylelintrc.json \"src/**/*.scss\" --formatter verbose",
"lint": "eslint --max-warnings=0 --fix --ext .ts,.tsx .",
"format": "prettier --write './**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc"
}

Open the package.json and add the lint-staged config

{
"lint-staged": {
"src/**/*.{ts,tsx}": ["npm run format", "npm run lint"],
"src/**/*.scss": "npm run style-lint"
}
}

clarify the husky & link-staged running

git add .
git commit -m "commit with husky and lint-staged"

$ /.bin/lint-staged
✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
✨ Done in 5.89s.

Enable gi hook & add a pre-commit hook

npx husky install
npx husky add .husky/pre-commit "yarn lint-staged"

So you can see at the root of the folder a new folder .husky created

.husky
-- _
-- .gitignore
-- husky.sh
-- pre-commit

Content of pre-commit file

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

yarn lint-staged

I hope the article above helps you with understanding how to create a reaction with useful tools works together. For now, let’s end it here. And I’m excited you are here! feel free to comment on any problem and I am happy to help

(づ。◕‿‿◕。)づ Github: https://github.com/kobee-tech-stack/react-typescript-template/

--

--

I’m working at KMS-Technology company. I love code (▀̿Ĺ̯▀̿ ̿) — Full Stack Software Engineer