Setting Up a React Project from Scratch

Alice Moretti
7 min readDec 7, 2021

During this year I’ve had the chance to play around with React while implementing the following projects:

  • my website: https://www.alicemoretti.com/ ,
  • a simple page fetching data from an external API and using useState, useEffect, and useParams,
  • a blog website that allows users to read blogs, add them, and delete them. As a side note, I have coded this project while following an excellent React tutorial I highly recommend (Full React Tutorial by The Net Ninja),
  • the blog you are reading that is implemented with Gatsby.js, a React-based framework,
  • a wedding website I recently finalized for a client that is also made with Gatsby.js.

The path to becoming a skilled React developer is still long but I am confident this will be the outcome of my self-learning journey :-)

Before my second child’s arrival (might be in a couple of weeks, who knows), I had the desire to revise the basics of React and I have decided to do this by following a super interesting React course on Frontend Master, the Complete Intro to React V6 by Brian HoIt. In this blog post, and hopefully a couple more (depending on when the baby will pop) I’ll try to share what I have learned, especially focusing on the topics that I have found more interesting and hard to understand.

What I like about this tutorial is that it teaches you React from scratch. No create-react-app command is used but instead, the course starts by creating a simple index.html file. All the necessary packages (npm, Prettier, ESLint, Parcel, Babel, React) are added manually.

Why would you bother to type all this code manually when you could start from a nice boilerplate you might wonder? I believe it can be eye-opening to understand the underlying structure and logic of a React application (especially for people who, like me, recently took up coding without any IT background whatsoever). Honestly, before bumping into this tutorial I barely asked myself what magic was working behind the scenes while running create-react-app. For many months it had been enough for me to run “npm start” inside the terminal and see my styled website appearing inside the browser.

Now I felt it was time to dig a bit more beneath the surface.

React and ReactDOM

Immediately after writing the index.html page, I have learned that React requires two packages to render, React and ReactDOM.

  • React is the high-level API, it contains all the methods but doesn’t contain a way to render itself inside the browser.
  • ReactDOM is the library interacting with the DOM (duh..), necessary for our application to be visible inside the browser.

I have understood that the two were split into separate packages after the arrival of React Native. These two packages, before adding all the necessary dependencies to the project, are initially loaded from the cdn inside the index.html file with the following code:

<script src="https://unpkg.com/react@17.0.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.1/umd/react-dom.development.js"></script>

Creating the first component

The main App.js component is initially coded inside the index.html page itself. As we will see below, to create a separate component we will need to install a JavaScript bundler called Parcel.

<script>
const App = () => {
return React.createElement(
"div",
{},
React.createElement("h1", { id: "my-brand" }, "Adopt me")
);
};
ReactDOM.render(
React.createElement(App),
document.getElementById("root")
);
</script>

Above we are creating the component “App” with the following structure: a div without attributes (the curly braces can contain possible attributes and/or arias) containing an h1 with id “my-brand” and text “Adopt me”. Interestingly, when using JSX syntax, we no longer need to use the createElement method as JSX automatically transpiles into createElement calls.

ReactDOM.render is what takes our App component and puts it into the DOM, inside the element with the id “root”. Note the usage of React.createElement method with the App component as a parameter. We need to create an instance of App in order to render the component itself.

npm

You might laugh but I didn’t know that to create a package.json file I had to run “npm init” inside the terminal :-)

Package.json is the file that tracks all the dependencies a project needs in order to run. For example, when we clone on our machine a repository from GitHub, we normally need to run “npm install” that automatically installs all the dependencies listed inside the package.json file (these are normally added inside the node_modules folder).

Once we run “npm init” the npm project is initiated and we can import code from the npm registry, which is a bunch of open-source modules that people have written and everyone can use.

Git

It was also a good reminder that Git doesn’t magically land on your React project but that, if you don’t use create-react-app you need to manually initialize a git repository with the “git init” command. Mind that the git repository needs to be initialized inside the root of the project!

Also, I had never bothered to think that a .gitignore file could be created manually (yes you might yet be laughing another time). In a previous tutorial I had followed, I had to add some environment variables necessary to connect to a headless CMS and the .gitignore file was already there (it was a Gatsby project that came with a nice boilerplate).

As a side note, for those who are interested in learning more about Git, I share these two useful links I was recommended while attending a Codebar event here in Helsinki.

Parcel

Through the command “npm install -D parcel@1.12.3”, I then added Parcel, which initially I had no clue what it was.

Parcel (in technical jargon a JavaScript bundler) acts as the glue that enables your React application to run. It is the one that puts together all the pieces of the puzzles (CSS files, js files/components, dependencies) while enabling a live server. Yes, the magic live server I used to launch with “npm start” without understanding how the browser could interpret all those files and information…

The way it works is that you give it an entry point, in this case, the index.html file, and from there it is enough smart to understand, find and include all the dependencies and .js files necessary to build the application (for a more thorough explanation see the official Parcel documentation).

The entry point is defined inside the package.json as follows:

"scripts": {
"dev": "parcel src/index.html",
}

Indeed, once Parcel had been installed, I could move the App component into a separate file! Thanks to Parcel, the application is being rendered to the browser even though the components are scattered around different files! Component logic unveiled!

With Parcel being added I was then able to remove the React and ReactDOM dependencies being added from unpkg.com from the index.html file and add them to the node_modules directory by running “npm install react@17.0.1 react-dom@17.0.1.” To use React inside the components I then added the following code:

import React from "react";
import ReactDOM from "react-dom";

I am new to the topic and cannot provide any good comparison but I understand from the tutorial that alternatives to Parcel are the following ones:

  • Webpack
  • Browserify
  • esbuild
  • Rollup

Babel (not the language learning app)

Coming from a university background in language studies, for me Babel, even though spelled differently, was the app to learn languages. It was interesting to find out that it is a transpiler to the project which transpiles newer JavaScript versions to older ones (but also JSX and typescript) so that older browsers can understand. During the past months, I had never wondered how a browser could understand JSX…

So, after all, it seems that both Babel and Babbel are named after the “Tower of Babel’” myth, which explains why the world’s peoples speak different languages. This makes me feel slightly less stupid :-)

Babel can also be configured by adding the file .babelrc inside the root folder. In this case, the following code was added:

{
"presets": [
[
"@babel/preset-react",
{
"runtime": "automatic"
}
]
]
}

And by adding “runtime automatic” we can omit to import React from ‘react’ at the top of every JSX file.

As said above, Babel allows the browser to understand the JSX syntax, and thus I could switch the Pet.js initial syntax to JSX which is way more convenient to type.

/*
const Pet = (props) => {
return React.createElement("div", {}, [
React.createElement("h1", {}, props.name),
React.createElement("h3", {}, props.animal),
React.createElement("h3", {}, props.breed),
]);
};
*/

/*When the JSX below runs through Babel and Parcel, it outputs the code above.
*/
const Pet = (props) => {
return (
<div>
<h2>{props.name}</h2>
<h3>{props.animal}</h3>
<h3>{props.breed}</h3>
</div>
);
};

export default Pet;

Browserslist

Finally, it was interesting to see the following configuration inside the package.json file:

"browserslist": [
"last 2 Chrome versions",
"last 2 Firefox versions"
]

What happens here is that Babel can transform the JSX code from futuristic code to code that is understandable by older browsers. With a package called Browserslist (that Parcel automatically installed for me) I can decide which browsers Babel will target.

With this, I have covered the first part of the course which was mainly about setting up all the necessary JavaScript tools to start working on the React project (this was just the beginning…). In the coming blog posts, I will talk more in detail about hooks and React Router (my favorite topic as I constantly get stuck over it :-) ).

If you think my blog post can be improved or you find some statement to be wrong please send me a message through this form. I always look forward to learning and connecting with people who are passionate about coding and talking tech through simple words.

--

--

Alice Moretti

Frontend-developer, nature addicted, runner, coffee & yoga lover living in Helsinki.