Create-react-app with VS Code
Tags: javascript, react, webdev, beginners
Published: 2019-06-20 14:49:18

_Set up a basic React development environment using create-react-app and VS Code_


## Requirements
- [VS Code](https://code.visualstudio.com/)
- [Node.js](https://nodejs.org)

_Note: I uploaded the final code on [GitHub](https://github.com/tducasse/setup-react)._

## Create a new project using create-react-app
[create-react-app](https://github.com/facebook/create-react-app) provides a very easy way to generate a React app in seconds. This is currently developed by Facebook, and the recommended way to start a new project.
Open a terminal and go to the desired folder (create-react-app will create a folder for your app).
```bash
cd ~/Projects # this is my projects folder
npx create-react-app my-app # replace `my-app` with the name of your app
cd myapp
npm start
```

You should see something like this:
![react-app.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1561037381611/U2dPz0e03.png)

### Folder structure
The script will generate a few files, and it should look something like this:
![architecture.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1561037397601/XVONw9BKB.png)

Let's have a look at what's been created:
1. `package.json`: This file is related to npm. It holds our dependencies (the libraries you want to be able to use in your code). You can also describe your application, add useful scripts in order to automate common tasks, such as running tests, starting a server, deploying, etc.
- `package-lock.json`: This is auto-generated by npm every time you add a new dependency. You should never have to touch it, and it is good practice to commit it to your repository.
- `.gitignore`: When you commit files to a git repository, git will (by default) want to add every file that's in your project. But sometimes you might want to exclude a file, and `.gitignore` is exactlly that. By default, create-react-app excludes `node_modules` for example, which is the folder containing all our dependencies. Since we are going to commit `package.json` and `package-lock.json` anyway, there is no need at all to commit them (plus they are _super_ heavy).
- **`public` folder**: This is where we find the root of our application, `index.html`, and our favicon, `favicon.ico`.
- **`src` folder**: Our app folder. This is where our code lives, and where we are going to spend 98% of our time.

### Let's have a look at the code
First, let's go to `index.html`, and have a look at this line:
```html
...
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
// the next line
    <div id="root"></div>

...
```

This will be the HTML element to which the React application will be attached.

`index.js` is the first file that will be loaded in our application.

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

// the next line
ReactDOM.render(<App />, document.getElementById('root'));
```

This line is the one that actually links our React app to the DOM (`root` node, as we've seen just before).

```jsx
// the two next lines
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
```

These two first lines are everything that's necessary to write React code.
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
// the two next lines
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
```

These ones are just importing our React components (here `App`), and our CSS files.

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// the next line
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
```

This last line is used only if you are writing a PWA (Progressive Web App, more on this [here](https://developers.google.com/web/progressive-web-apps/)). Yes, create-react-app is already configured as a PWA!

So what is this `App.js` doing? Let's have a look:
```jsx
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

At the beginning, you can see the standard `import React from 'react'` that you need to include in every file that uses `jsx` (this cool HTML-like syntax that we use to write React components).
You may have noticed that we import a file called `App.css`.
Open it, and look at what's written here:
```css
.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

```

I'm not going to spend too much time on this, but let's take the example of the first class:
```css
.App {
  text-align: center;
}
```

And let's see how we use it in a React component:
```jsx
function App() {
  return (
    // the next line
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
```

As you can see, the main difference with "normal" HTML is that the name of the attribute is `className`, instead of `class`.

## Configuring VS Code
Enough about `create-react-app` and the code it generated, it's time to configure our code editor.
VS Code has pretty good defaults (syntax highlighting, autocompletion, 'go to definition', etc). But you can make it even better!

### ESlint
Since JavaScript is not a compiled language, there is nothing that can tell us if something _looks_ like it's going to fail before we actually run it. ESLint solves exactly this problem.

[ESLint](https://eslint.org/) is the most popular JavaScript **linter**. A linter is a program that analyses your code, and tries to find potential errors, ahead of runtime. ESLint is highly configurable, and you can extend premade sets of rules, define your own rules, override existing rules, etc.

Luckily, create-react-app already comes with ESlint. So we don't have _much_ to do!

Install the [ESLint extension for VS Code](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). This will allow us to see the result of ESLint directly in VS Code.

Once installed, you can quickly test it. Go to `App.js` again, and remove this line:
```jsx
<a
    className="App-link"
    href="https://reactjs.org"
    target="_blank"
    // the next line
    rel="noopener noreferrer"
  >
```

VS Code should start _yelling_ at you:
![eslint.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1561037447706/H_0OLLhUo.png)

### Prettier
[Prettier](https://prettier.io/) is an opinionated code formatter. People used to fight for hours around commas, semi-colons, etc. Prettier is an attempt at ending the debate. Since most editors have a Prettier plugin, you can "autoformat on save", which means you can write ugly code, and never worry about formatting!

You can use Prettier in different ways. My favorite one is to run it as part of the ESLint rules.

First, install the Prettier dependencies:
```bash
npm i -D prettier eslint-config-prettier eslint-plugin-prettier
```

Then, create a file, at the root of your app, called `.eslintrc.json` as such:
```json
{
  "extends": [
    "react-app",
    "prettier",
    "prettier/react"
  ],
  "plugins": [
    "prettier"
  ],
  "rules": {
    "prettier/prettier": "error"
  }
}
```

So what have we done?
- `eslint-config-prettier` is a package that allows us to disable the rules that would conflict with the rules defined by Prettier.
- `eslint-plugin-prettier` is the one that allows to run Prettier as an ESLint rule.

If you have a look at the `.eslintrc.json` file that we just created, you'll notice that we have added a rule that basically says "everything that Prettier reports should be treated as an error".

Once everything is saved, go back to `App.js` and have a look at what ESLint is saying now:
![eslint-prettier.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1561037460079/0Pr5vVAgd.png)

### Autoformatting
So this is all good, now we see what's wrong about our code, but wouldn't it be nice if we could just fix everything automatically? Replacing double quotes with single quotes should be pretty straightforward for a computer, right?

ESLint has an option to autofix every error that can be autofixed. On the command-line, it's `--fix`, and you can configure your VS Code so that this happens everytime you save.

Create a new folder, at the root of your app, called `.vscode`, and inside this folder, a file called `settings.json`:
```json
{
  "eslint.autoFixOnSave": true
}
```

Go back to `App.js`, and try saving your file now, it should get reformatted instantly!

### Precommit hook
So now that we have linting and formatting all sorted, what happens if someone decides to contribute to our code without setting up everything we just set up? It will break everything, and you will be back to coding-style hell. So what can we do about it?

Two packages will help us with that:
- [husky](https://github.com/typicode/husky) gives us a really easy way to set up git hooks.
- [lint-staged](https://github.com/okonet/lint-staged#readme) will lint the files that are ready to be committed.

First, install them with:
```bash
npm i -D lint-staged husky
```

Go to your `package.json` and add:
```json
"lint-staged": {
    "**/*.js": [
      "eslint --fix",
      "git add"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  }
```

And you're done! Now, every time you will try to commit unformatted files, `husky` will launch `lint-staged`, which will intercept the process and run ESLint first. And if there's an error ESLint can't fix, it will stop the whole process. Which means you can't commit code that doesn't work anymore!

### Absolute imports
It is very common in a React project to organise your code in multiple nested folders.

Let's say we decide to implement something like [Brad Frost's atomic design](http://bradfrost.com/blog/post/atomic-web-design/) for example. A common way to implement it would be (this example is on [GitHub](https://github.com/tducasse/setup-react)):
![atomic.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1561037473760/jAwGKrvDL.png)

`App.js` would import the `LoginPage` template like this:
```jsx
import React from "react";
// the next line
import LoginPage from "./components/templates/LoginPage";

function App() {
  return (
    <div style={{ padding: 20 }}>
      <LoginPage />
    </div>
  );
}

export default App;
```

This is all good! But now, if you go to `LoginPage.js`, and have a look at how we have to import `LoginPassword`:
```jsx
import React, { useState } from "react";
// the next line
import LoginPassword from "../organisms/LoginPassword";

const LoginPage = props => {
  return (
    <>
      <LoginPassword />
    </>
  );
};

export default LoginPage;
```

Notice the `../` to go up a folder? This will become really hard to follow once we start deeply nesting folders and files.

A good solution for that is something called **absolute imports**. At the root of your app, create a file called `jsconfig.json`:
```json
{
  "compilerOptions": {
    "baseUrl": "./src/"
  },
  "include": [
    "src"
  ]
}
```

Now you can import your files using an absolute path, starting from `./src/`:
```jsx
import React from "react";
// the next line
import LoginPassword from "components/organisms/LoginPassword";

const LoginPage = () => {
  return (
    <>
      <LoginPassword />
    </>
  );
};

export default LoginPage;
```

While it might not seem like a big deal right now, because we only have one level of nesting, big applications tend to have very deeply nested components, which makes imports look like `../../../../MyComponentFolder/MyComponent` very quickly!

_Find the final code on [GitHub](https://github.com/tducasse/setup-react)._