Guide to configure react app. Stack:
- Create project folder
mkdir ./test-project
cd ./test-project
- Install parcel
yarn add --dev parcel
# or
npm install --save-dev parcel
- Create index page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My First Parcel App</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
- Run app
yarn parcel src/index.html
# or
npx parcel src/index.html
- Add shortcut scripts to package.json
"scripts": {
"start": "parcel",
"build": "parcel build"
},
- Install React
yarn add react react-dom
# or
npm i react react-dom
- Create a react component and include it in script
- src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Parcel App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="index.js"></script>
</body>
</html>
- src/index.js:
import { createRoot } from "react-dom/client";
import { App } from "./App";
const container = document.getElementById("app");
const root = createRoot(container)
root.render(<App />);
- src/App.jsx:
export function App() {
return <h1>Hello world!</h1>;
}
TSC is the official TypeScript compiler from Microsoft. While Parcel’s default transpiler for TypeScript is much faster than TSC, you may need to use TSC if you are using some configuration in tsconfig.json
that Parcel doesn't support. In these cases, you can use the @parcel/transformer-typescript-tsc
plugin by adding it to your .parcelrc
.
.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
}
}
- Install typescript and types for default packages.
npm install @types/react @types/react-dom @types/jest --save-dev
# or
yarn add @types/react @types/react-dom @types/jest --dev
- Redux
npm install redux
npm install @types/react-redux --save-dev
# or
yarn add redux
yarn add @types/react-redux --dev
- Redux Saga
npm install redux-saga
# or
yarn add redux-saga
- React Query
npm install react-query
# or
yarn add react-query
- Install Router
npm install react-router react-router-dom
npm install @types/react-router-dom --save-dev
# or
yarn add react-router react-router-dom
yarn add @types/react-router-dom --dev
- Samples
type Props = {
redirectTo: string;
}
const RequireAuth: React.FC<Props> = ({ redirectTo }): JSX.Element => {
const { isAuthenticated } = useIsAuthenticated();
return isAuthenticated ? <Outlet /> : <Navigate to={redirectTo} />;
}
export const App: React.FC = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
<Route path="/settings" element={<RequireAuth redirectTo="/login" />}>
<Route index element={<Settings />} />
<Route path="account" element={<Account />} />
</Route>
</Routes>
</BrowserRouter>
)
}
Why ESLint? https://eslint.org/blog/2019/01/future-typescript-eslint
npm install @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb eslint-plugin-react eslint-plugin-react-redux eslint-plugin-redux-saga eslint-plugin-react-hooks eslint-plugin-import --save-dev
- create
.eslintrc.json
file for configuration
{
"extends": [
"airbnb",
"plugin:@typescript-eslint/recommended",
"plugin:react-redux/recommended",
"plugin:redux-saga/recommended"
],
"plugins": ["react-hooks", "react-redux", "redux-saga", "@typescript-eslint"],
"env": {
"browser": true,
"jasmine": true,
"jest": true
},
"rules": {
"react/jsx-handler-names": 1,
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"redux-saga/no-unhandled-errors": "off",
"react-redux/prefer-separate-component-file": "off",
"@typescript-eslint/interface-name-prefix": ["warn", "always"],
"@typescript-eslint/explicit-function-return-type": 1,
"import/order": [
"error",
{
"pathGroups": [
{
"pattern": "react",
"group": "external",
"position": "before"
},
{
"pattern": "./styles",
"group": "sibling",
"position": "after"
}
],
"groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
"pathGroupsExcludedImportTypes": ["react"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
]
},
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
},
"parser": "@typescript-eslint/parser"
}
- Create
.eslintignore
src/registerServiceWorker.js
src/**/__tests__/**
webpack/*
- Update
scripts
section in yourpackage.json
"scripts": {
"lint:fix": "eslint './src/**/*.{ts,tsx}'"
}
# or you can use your local esslint
npm i -g eslint
- Run linter
npm run lint:fix
# or you can use your local esslint
eslint --ext .ts,.tsx --fix --debug source/path-to-directory
eslint --fix --debug source/path-to-file/Component.tsx
- You need to have
TSLint
configured npm install tslint-config-prettier --save-dev
npm install tslint-plugin-prettier --save-dev
- Update your
tslint.json
file
{
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-config-prettier"
],
"rulesDirectory": [
"tslint-plugin-prettier"
],
"rules": {
"prettier": true
}
}
- Create
.prettierrc
{
"trailingComma": "none",
"singleQuote": true,
"printWidth": 120
}
- Update
scripts
section in yourpackage.json
{
"scripts": {
"tslint-check": "tslint-config-prettier-check ./tslint.json",
"prettier": "npm run tslint-check && prettier --write \"*/**/*.{ts,tsx,less}\""
}
}
- Run
npm run prettier