Editor’s Note: This post was updated on 28 March 2023 to include new sections on how to run tests with the React testing library, styling our React app with CSS, and a section on why you should use Create React App. To learn more about React, visit our archives here.
Create React App is a popular toolchain for building simple React apps. The goal of this post is to explain the components of Create React App at a deeper level to give you much better control and confidence over the development environment.
Jump ahead:
Before we understand what Create React App solves, let’s first learn what a toolchain is. In simple terms, a toolchain is a set of distinct software development tools linked by specific stages. In other words, any software development framework is made up of a bunch of supporting tools optimized to do specific functions. For instance, in C++ development, we need a compiler to compile the code and a build system like CMake to manage all the dependencies if the project is fairly big. In this case, the compiler and CMake become part of the toolchain.
In React development, different toolchains satisfy different requirements for product development. For instance, Next.js is great for building a server-rendered website, and Gatsby is optimized for static, content-oriented websites like blogs and newsletters.
Create React App is also a toolchain. It is specifically recommended by the React community for building single-page applications (SPAs) and for learning React (for building “Hello, World!” applications). It sets up your development environment so that you can use the latest JavaScript features, provides a nice developer experience, and optimizes your app for production.
Create React App was created by Joe Haddad and Dan Abramov. The GitHub repository is very active and maintained by the creators, along with many open source developers from different parts of the world. If you’re interested in contributing, the repository’s contributing page is an excellent place to start.
Create React App is a great tool for quickly getting up and running on new React projects. Some other reasons why you should use this tool are as follows:
Now that we have relevant context about Create React App let’s start by installing it. In this tutorial, we will build a simple SPA that displays restaurants on a webpage and lets users rate them.
Run the following npx command on a terminal to install and bootstrap the application using Create React App. Let’s call our application rate-restaurants
:
~ npx create-react-app rate-restaurants
This command runs for a few seconds and exits happily after creating a bare-bones React application under a new directory called rate-restaurants
. Now, cd
into the rate-restaurants
directory. The directory looks something like this:
node_modules
This folder is part of the npm system. npm puts local installs of packages in ./node_modules
of the current package root. Basically, the packages you want to use by calling an import
statement go here.
public
This folder contains the index.html
and manifest.json
files. Let’s look at the files inside the public
folder.
index.html
This index.html
serves as a template for generating build/index.html
, which is ultimately the main file served on the browser. Let’s take a look at this file’s contents:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <meta name="theme-color" content="#000000" /> <!-- manifest.json provides metadata used when your web app is installed on a user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ --> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <!-- Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> </body> </html>
Title
and meta
tagsThe <meta>
tags provide metadata about the HTML document. They describe the content of the page. <meta>
tags usually aren’t displayed on the webpage but are machine parsable. The bundled scripts are finally placed into the <body> title
of this HTML file.
In order to understand this, we need to learn about one more concept in the world of modern JavaScript toolchains, which is webpack. Think of webpack as a tool that bundles up all your source files and creates a single bundle.js
file that can be served from the index.html
file inside a <script>
tag.
This way, the number of HTTP requests made within the app is significantly reduced, which directly improves the app’s performance on the network. Besides, webpack also helps in making the code modular and flexible when you supply it with additional config options. Here’s a visual of it:
The above figure shows an example recipe app built using React and bundled using webpack. Webpack has a webpack.config.js
file, which is used to specify the configuration settings. It typically looks something like this:
const path = require('path'); module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' } };
The entry
key specifies the entry point for webpack, and output
specifies the location where the bundle.js
file will be stored after the build process.
Coming back to index.html
, Create React App uses html-webpack-plugin for bundling. If you look at the webpack.config.js
here, the entry
key points to src/index.js
, which specifies the entry point for webpack. When webpack compiles the assets, it produces a single bundle (or several, if you use code splitting). It makes their final paths available to all plugins  —  one such plugin is for injecting scripts into HTML.
The html-webpack-plugin is also enabled to generate the HTML file. In Create React App’s webpack.config.js
, it is specified that it should read public/index.html
as a template. The inject
option is also set to true
. With that option, html-webpack-plugin adds a <script>
with the path provided by webpack right into the final HTML page.
This final page is the one you get in build/index.html
after running npm run build
, and the one that gets served from /
when you run npm start
. Now that we understand index.html
, let’s move on to manifest.json
.
This is a web app manifest that describes your application, and it’s used by mobile phones if a shortcut is added to the home screen. Let’s look at the contents to understand it further:
{ "short_name": "React App", "name": "Create React App Sample", "icons": [ { "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" } ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }
The contents of this file are pretty self-explanatory. But where are these values used? When a user adds a web app to their home screen using Google Chrome or Firefox on Android — or Safari on iOS — the metadata in manifest.json
determines what icons, names, and branding colors to use when the web app is displayed. The web app manifest guide provides more context about what each field means, and how your customizations will affect your users’ experience. Basically, the information read from this file is used to populate the web app’s icons, colors, names, etc.
favicon.ico
This is simply the icon image file used for our application. You can see this linked inside index.html
and manifest.json
. Before moving on to the src/
directory, let’s look at a couple other files on our root.
package.json
This file lists the packages your project depends on and which versions of a package your project can use. In tandem with either package-lock.json
or yarn.lock
(more on these files below), it also makes your build reproducible and, therefore, easier to share with other developers.
The scripts
field is of particular interest here. You can see that the start
, build
, test
, and eject
commands point to react-scripts’ version of start
, build
, test
, and eject
. This specifies that when you run npm commands like npm start
, it will actually run react-scripts start
.
react-scripts is a set of scripts from the Create React App starter pack. react-scripts start
sets up the development environment and starts a server, as well as convenient development features such as hot module reloading. You can read here to see everything it does for you.
yarn.lock / package-lock.json
Before learning the purpose of yarn.lock
, let’s first understand what Yarn is. Yarn is a package manager for JavaScript dependencies. It is an alternative to the default package manager that ships with every Node.js installation, which is called npm. Package managers allow you to use other developers’ solutions to different problems, making it easier for you to develop your own software. Code is shared through packages, sometimes referred to as modules.
Create React App will detect if you have Yarn installed and if so will use that to install dependencies rather than npm. If you don’t have Yarn installed, npm will be used and you will see a package-lock.json
file rather than the yarn.lock
file.
In order to get consistent installs across machines, Yarn needs more information than the dependencies you configure in your package.json
. Yarn needs to store exactly which versions of each dependency were installed. That’s what the yarn.lock
file (or package-lock.json
file if npm is used) in the root of your project is for.
Now, let’s fire up the application. To run the app, you can either run npm start
or yarn start
. Once you run the command, open http://localhost:3000 to view the application.
Note that npm run build
or yarn build
will build the app for production and store it inside the build/
folder, which can be deployed to production. For the sake of this tutorial, let’s use npm start
for development instead of building the app for production. Your app should look like this:
Let’s try and understand what the entry point is for this app. When we looked at webpack, I mentioned that webpack’s entry is index.js
, which is the entry point for the React application.
The index.js
file has the following line:
const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );
This line calls ReactDOM
’s render()
method, which renders a React element into the DOM in the supplied container and returns a reference
to the component. The React element here is the <App>
component, and the supplied container is the DOM element root
(which is referenced in index.html
).
<App>
is the root component of this app. Let’s look at App.js
, where it is defined:
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 src/App.js
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;
The App
component is a function for defining a React component. This is the code that we are interested in. Any application can be built by stripping stuff out and tweaking the App.js
. We can even build React components separately inside a src/components/
folder and import these components inside App.js
. A typical React application looks something like this:
There is a root component, <App>
, that imports other child components, which in turn import other child components. Data flows from root to children through React properties (called props
) and flows back up using callback functions. This is the design pattern used by any basic React application.
At this point, we should be able to start building any simple single-page application by tweaking App.js
and adding the necessary components. The App.css
file can be used for styling the application.
React Testing Library is a testing utility for React that provides a simple and intuitive way to test React components. It is built on top of the DOM Testing Library, which provides a set of utilities for testing DOM nodes in a browser-like environment.
Instead of concentrating on implementation details, React Testing Library encourages developers to build tests that mimic how consumers interact with the application. As a result, tests created with the React Testing Library ought to be more reliable and less prone to fail when a component’s implementation is changed.
The React Testing Library comes inbuilt with Create React App. This means that you do not have to install additional dependencies before getting started with it in a React application. The first step in using the React testing library is by creating a file ending in .test.js
. Next, we import React Testing Library into the file by adding the following line at the top of the file:
import { render, screen } from '@testing-library/react';
We import the file that we want to test in the next line, as shown below:
import App from './App';
The next step is to write out the cases that we want to test for and then check if the component works as expected:
// The imports remain the same test('renders learn react link', () => { render(<App />); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); });
In the code block above, we are writing a test case that renders the App
component and then checks to see if there is any text like learn react
on the screen. The next step is to run our test with the yarn test
command. The command will run our test and display it in the terminal as shown below:
We can check if this is working by intentionally failing out test and then running yarn test
again:
Our final app will look something like this:
The first step is to write our app’s stateless components, which we’ll need to build the cards with the data and rating system in them. In order to do this, we create a folder called components/
inside src/
and add a file called Card.js
:
import React from 'react'; const CardBox = (props) => { return <div className="card-body">{props.children}</div>; }; const Image = (props) => { return <img src={props.image} alt="Logo" className="picture" />; }; const Name = (props) => { return <div className="name">{props.name}</div>; }; const Details = (props) => { return <div className="details">{props.details}</div>; }; const Star = ({ selected = false, onClick = (f) => f }) => ( <div className={selected ? 'star selected' : 'star'} onClick={onClick}></div> ); const Card = (props) => { return ( <CardBox> <div className="inner-body"> <Image image={props.image} /> <div className="body"> <div className="inner-body"> <Name name={props.name} /> </div> <Details details={props.details} /> <div className="inner-body"> {[...Array(5)].map((n, i) => ( <Star key={i} selected={i < props.starsSelected} onClick={() => props.change(props.id, i + 1)} /> ))} </div> </div> </div> </CardBox> ); }; export default Card;
As you can see, we are creating a separate stateless component for each element inside the card — namely, the restaurant name
, details
, image
, and the rating section
. Then, we wrap all of this inside a Card
component and export it as a default
:
import { useState } from 'react'; import './App.css'; import Card from './components/Card'; import { v4 as uuidv4 } from 'uuid'; function App() { const [restaurants, setRestaurants] = useState([ { id: uuidv4(), name: 'Sushi S', details: '2301 Moscrop Street, Burnaby, BC V61 23Y', image: 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80', starsSelected: 0, }, { id: uuidv4(), name: 'Agra Tandoori', details: '1255 Canada Way, Burnaby, BC V61 23Y', image: 'https://images.unsplash.com/photo-1552566626-52f8b828add9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80', starsSelected: 0, }, { id: uuidv4(), name: 'Bandidas Taqueria', details: '2544 Sanders Avenue, Richmond, BC V6Y 0B5', image: 'https://images.unsplash.com/photo-1537047902294-62a40c20a6ae?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80', starsSelected: 0, }, ]); const onChange = (id, starsSelected) => { setRestaurants( [...restaurants].map((restaurant) => { if (restaurant.id === id) { restaurant.starsSelected = starsSelected; } return restaurant; }) ); }; return ( <div className="main-body"> {[...restaurants].map((restaurant, index) => ( <Card key={index} name={restaurant.name} details={restaurant.details} image={restaurant.image} starsSelected={restaurant.starsSelected} id={restaurant.id} change={(id, starsSelected) => onChange(id, starsSelected)} /> ))} </div> ); } export default App;
In the App.js
, we import Card
. The restaurant data is modeled as the state
of this app. Saving the state separately in a file outside of App.js
is a better design as the app and its restaurant data grow. In the return()
function, we pass this data to the Card
component as props.
Data flows down to child components as properties and flows back up through callbacks, the OnChange
callback used for updating the star ratings. That’s it! Now, when you go to http://localhost:3000/, you should see the rate restaurant app, ready to go.
We are done building the functionality of the application. The next step is how to go about styling the application and making it look exactly how we want. Create React App makes it easier for us to use CSS as it comes with inbuilt CSS support. All we need to do is copy the code below and paste it into the App.css
file:
// App.css .main-body { display: flex; flex-direction: column; background-color: #11171d; min-height: 80rem; } .body { display: flex; flex-direction: column; } .inner-body { display: flex; flex-direction: row; } .card-body { display: flex; flex-direction: column; width: 566px; height: 170px; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5); background-color: #15202a; margin-left: 25rem; margin-bottom: 0.1rem; } .card-body:hover { background-color: #11171d; border: #ffffff; } .picture { margin-left: 24px; margin-top: 17px; border-radius: 50%; width: 48px; height: 48px; } .name { display: flex; flex-direction: row; margin-left: 15px; margin-top: 19px; min-width: 85px; height: 17px; font-family: HelveticaNeue; font-size: 14px; font-weight: 500; font-style: normal; font-stretch: normal; line-height: normal; letter-spacing: -0.6px; color: #ffffff; } .details { margin-left: 15px; margin-top: 7px; width: 445px; height: 88px; font-family: HelveticaNeue; font-size: 14px; font-weight: 300; font-style: normal; font-stretch: normal; line-height: normal; letter-spacing: -0.6px; color: #ffffff; } .star { cursor: pointer; height: 25px; width: 25px; margin-left: 0px; float: left; background-color: grey; clip-path: polygon( 50% 0%, 63% 38%, 100% 38%, 69% 59%, 82% 100%, 50% 75%, 18% 100%, 31% 59%, 0% 38%, 37% 38% ); } .star.selected { background-color: red; }
With that done, we see our tastefully styled application when you navigate to the browser. You can, however, choose to use more advanced CSS configurations like Sass and/or CSS frameworks like Tailwind CSS or styled-components in your application.
Hot Module Replacement (HMR) is a feature in webpack to inject updated modules into the active runtime. It’s like LiveReload for every module. HMR is opt-in, so you need to input some code at chosen points of your application. The dependencies are handled by the module system.
So, how do you enable this in a project created using Create React App? This is quite simple! Just add the following code inside index.js
, and HMR is ready to go:
// regular imports ReactDOM.render(<App /> , document.getElementById('root')) if (module.hot) { module.hot.accept('./App', () => { ReactDOM.render(<App />, document.getElementById('root')) }) }
Finally, for some motivation to use Create React App for building apps, let’s look at some of the well-known products bootstrapped and built using Create React App. CRA provides a development server, builds scripts, and many other useful features out-of-the-box, which helps developers to focus on writing code and building UI rather than setting up the development environment. Popular apps created with CRA include:
This GitHub comments section also has a long list of production-ready apps built using Create React App. A couple of the ideas are even part of Y-Combinator.
I hope you now understand the different elements of Create React App better. What are you waiting for? Fire that terminal up, install Create React App, and start building your awesome ideas!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowThe useReducer React Hook is a good alternative to tools like Redux, Recoil, or MobX.
Node.js v22.5.0 introduced a native SQLite module, which is is similar to what other JavaScript runtimes like Deno and Bun already have.
Understanding and supporting pinch, text, and browser zoom significantly enhances the user experience. Let’s explore a few ways to do so.
Playwright is a popular framework for automating and testing web applications across multiple browsers in JavaScript, Python, Java, and C#. […]
5 Replies to "Getting started with Create React App"
When I run npx create-react-app today it outputs a horrible version of App.js
import React from ‘react’;
function App() {
return (
How do I get the standard es6 version back?
React was created by Jordan Walke, not Joe Haddad and Dan Abramov.
That is true, but the author didn’t say they created React, he said they created CRA
In “TITLE AND META TAGS”, line 15..-ish: “…This way, the number of HTML requests..” —let it be “…HTTP requests…”…
đź‘Ť