Chapter 1: Creating a Single-Page Application in React

When you bought this book, you'd probably heard of React before and maybe even tried out some of the code examples that can be found online. This book is constructed in such a way that the code examples in each chapter gradually increase in complexity, so even if you feel your experience with React is limited, each chapter should be understandable if you've read the previous one. By the end of this book, you will know how to work with React and its stable features, up until version 18, and you will also have experience with GraphQL and React Native.

This first chapter kicks off with us learning how to build a single-page application based on the popular TV show Rick and Morty; the application will provide us with information about its characters that we'll fetch from an external source. The core concepts for getting started with React will be applied to this project, which should be understandable if you've got some prior experience in building applications with React. If you haven't worked with React before, that's no problem either; this book describes the React features that are used in the code examples along the way.

In this chapter, we'll cover the following topics:

  • Setting up a new React project
  • Structuring a project

Let's dive in!

Project overview

In this chapter, we will create a single-page application in React that retrieves data from an API and runs in the browser with Webpack and Babel. Styling will be done using Bootstrap. The application that you'll build will show information about the popular TV show Rick and Morty, along with images.

The build time is 1 hour.

Getting started

The complete code for this chapter can be found on GitHub: https://github.com/PacktPublishing/React-Projects-Second-Edition/tree/main/Chapter01.

For the applications created in this book, you'll need to have at least Node.js v14.17.0 installed on your machine so that you can run npm commands. If you haven't installed Node.js on your machine, please go to https://nodejs.org/en/download/, where you can find the download instructions for macOS, Windows, and Linux.

After installing Node.js, run the following commands in your command line to check the installed versions:

  • For Node.js (which should be v14.17.0 or higher), use this:

    node -v

  • For npm (which should be v6.14.3 or higher), use this:

    npm -v

Also, you should have installed the React Developer Tools plugin (for Chrome and Firefox) and added it to your browser. This plugin can be installed from the Chrome Web Store (https://chrome.google.com/webstore) or Firefox Add-ons (https://addons.mozilla.org).

Creating a single-page application

In this section, we will create a new single-page React application from scratch, starting with setting up a new project with Webpack and Babel. Setting up a React project from scratch will help you understand the basic needs of a project, which is crucial for any project you create.

Setting up a project

Every time you create a new React project, the first step is to create a new directory on your local machine. Since this is the first chapter for which you're going to build a single-page application, name this directory chapter-1.

Inside this new directory, execute the following from the command line:

npm init -y

Running this command will create a fresh package.json file with the bare minimum of information needed to run a JavaScript/React project. By adding the -y flag to the command, we can automatically skip the steps where we set information such as the name, version, and description.

After running this command, the following package.json file will be created for the project:

{

  "name": "chapter-1",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo "Error: no test specified" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC"

}

Note

To learn more about the workings of package.json, make sure to read the documentation from npm: https://docs.npmjs.com/cli/v6/configuring-npm/package-json.

After creating package.json in this section, we're ready to add Webpack, which we will do in the next section.

Setting up Webpack

To run the React application, we need to install Webpack 5 (at the time of writing, the current stable version of Webpack is version 5) and the Webpack CLI as devDependencies. Webpack is a library that lets us create a bundle out of JavaScript/React code that can be used in a browser. The following steps will help you set up Webpack:

  1. Install the required packages from npm using the following command:

    npm install --save-dev webpack webpack-cli

  2. After installation, these packages are included inside the package.json file where we can have them run in our start and build scripts. But first, we need to add some files to the project:

    chapter-1

      |- node_modules

      |- package.json

    + |- src

    +    |- index.js

This will add the index.js file to a new directory called src. Later on, we'll configure Webpack so that this file is the starting point for our application.

  1. First, the following code block must be added to this file:

    console.log('Rick and Morty');

  2. To run the preceding code, we will add the start and build scripts to our application using Webpack. The test script is not needed in this chapter, so this can be deleted. Also, the main field can be changed to private with the true value, as the code we're building is a local project:

      {

        "name": "chapter-1",

        "version": "1.0.0",

        "description": "",

        "main": "index.js",

        "scripts": {

    -     "test": "echo "Error: no test specified" &&

                   exit 1"

    +     "start": "webpack --mode development",

    +     "build": "webpack --mode production"

        },

        "keywords": [],

        "author": "",

        "license": "ISC"

      }

The npm start command will run Webpack in development mode, while npm run build will create a production bundle using Webpack. The biggest difference is that running Webpack in production mode will minimize our code and decrease the size of the project bundle.

  1. We now run the start or build command from the command line; Webpack will start up and create a new directory called dist:

    chapter-1

      |- node_modules

      |- package.json

    + |- dist

    +    |- main.js

      |- src

         |- index.js

  2. Inside this directory, there will be a file called main.js that includes our project code and is also known as our bundle. If successful, the following output will be visible:

    asset main.js 794 bytes [compared for emit] (name: main)

    ./src/index.js 31 bytes [built] [code generated]

    webpack compiled successfully in 67 ms

Depending on whether we've run Webpack in development or production mode, the code will be minimized in this file.

  1. You can check whether your code is working by running the main.js file in your bundle from the command line:

    node dist/main.js

This command runs the bundled version of our application and should return the following output:

> node dist/main.js

Rick and Morty

Now, we're able to run JavaScript code from the command line. In the next part of this section, we will learn how to configure Webpack so that it works with React.

Configuring Webpack to work with React

Now that we've set up a basic development environment with Webpack for a JavaScript application, we can start installing the packages we need in order to run any React application.

These packages are react and react-dom, where the former is the generic core package for React and the latter provides an entry point to the browser's DOM and renders React. Install these packages by executing the following command in the command line:

npm install react react-dom

Installing only the dependencies for React is not sufficient to run it, since, by default, not every browser can read the format (such as ES2015+ or React) that your JavaScript code is written in. Therefore, we need to compile the JavaScript code into a readable format for every browser.

For this, we'll use Babel and its related packages to create a toolchain to use React in the browser with Webpack. These packages can be installed as devDependencies by running the following command:

npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react

Next to the Babel core package, we'll also install babel-loader, which is a helper so that Babel can run with Webpack and two preset packages. These preset packages help determine which plugins will be used to compile our JavaScript code into a readable format for the browser (@babel/preset-env) and to compile React-specific code (@babel/preset-react). With the packages for React and the correct compilers installed, the next step is to make them work with Webpack so that they are used when we run our application.

To do this, configuration files for both Webpack and Babel need to be created in the src directory of the project:

chapter-1

  |- node_modules

  |- package.json

+ |- babel.config.json

+ |- webpack.config.js

  |- dist

     |- main.js

  |- src

     |- index.js

The configuration for Webpack is added to the webpack.config.js file to use babel-loader:

module.exports = {

module: {

   rules: [

     {

       test: /.js$/,

       exclude: /node_modules/,

       use: {

         loader: 'babel-loader'

       },

     },

   ],

},

};

The configuration in this file tells Webpack to use babel-loader for every file that has the .js extension and excludes files in the node_modules directory for the Babel compiler.

To use the Babel presets, the following configuration must be added to babel.config.json:

{

  "presets": [

    [

      "@babel/preset-env",

      {

        "targets": {

          "esmodules": true

        }

      }

    ],

    [

      "@babel/preset-react",

      {

        "runtime": "automatic"

      }

    ]

  ]

}

@babel/preset-env must be set to target esmodules in order to use the latest Node modules. Also, defining the JSX runtime to automatic is needed, since React 18 has adopted the new JSX Transform functionality: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html.

Note

The configuration for babel-loader can also be placed in the configuration inside webpack.config.json. But by creating a separate Babel configuration file for this, these settings can also be used by other tools in the JavaScript/React ecosystem.

Now that we've set up Webpack and Babel, we can run JavaScript and React from the command line. In the next part of this section, we'll create our first React code and make it run in the browser.

Rendering a React project

With the packages we've installed and configured in the previous sections to set up Babel and Webpack, we need to create an actual React component that can be compiled and run. Creating a new React project involves adding some new files to the project and making changes to the setup for Webpack:

  1. Let's edit the index.js file that already exists in our src directory so that we can use react and react-dom. The contents of this file can be replaced with the following:

    import ReactDOM from 'react-dom/client';

    function App() {

      return <h1>Rick and Morty</h1>;

    }

    const container = document.getElementById('app');

    const root = ReactDOM.createRoot(container);

    root.render(<App />);

As you can see, this file imports the react and react-dom packages, defines a simple component that returns an h1 element containing the name of your application, and has this component rendered in the browser with react-dom. The last line of code mounts the App component to an element with the root ID selector in your document, which is the entry point of the application.

  1. We can create a file that has this element in a new directory called public and name that file index.html:

    chapter-1

      |- node_modules

      |- package.json

      |- babel.config.json

      |- webpack.config.js

      |- dist

         |- main.js

    + |- public

    +    |- index.html

      |- src

         |- index.js

  2. After adding a new file called index.html to this directory, we add the following code inside it:

    <!DOCTYPE html>

    <html lang="en">

      <head>

        <meta charset="UTF-8" />

        <meta name="viewport" content="width=device-width,

          initial-scale=1.0" />

        <meta http-equiv="X-UA-Compatible"

          content="ie=edge" />

        <title>Rick and Morty</title>

      </head>

      <body>

        <section id="root"></section>

      </body>

    </html>

This adds an HTML heading and body. Within the head tag is the title of our application, and inside the body tag is a section with the "root" ID selector. This matches with the element we've mounted the App component to in the src/index.js file.

  1. The final step in rendering our React component is extending Webpack so that it adds the minified bundle code to the body tags as scripts when running. Therefore, we should install the html-webpack-plugin package into our devDependencies:

    npm install --save-dev html-webpack-plugin

To use this new package to render our files with React, the Webpack configuration in the webpack.config.js file must be extended:

+ const HtmlWebpackPlugin =

    require('html-webpack-plugin');

  module.exports = {

    module: {

      rules: [

        {

          test: /.js$/,

          exclude: /node_modules/,

          use: {

            loader: 'babel-loader',

          },

        },

      ],

    },

+   plugins: [

+     new HtmlWebpackPlugin({

+       template: './public/index.html',

+       filename: './index.html',

+     }),

+   ],

};

Now, if we run npm start again, Webpack will start in development mode and add the index.html file to the dist directory. Inside this file, we'll see that, inside our body tag, a new scripts tag has been inserted that directs us to our application bundle – that is, the dist/main.js file. If we open this file in the browser or run open dist/index.html from the command line, it will return the result directly inside the browser. We can do the same when running the npm run build command to start Webpack in production mode; the only difference is that our code will be minified:

Figure 1.1 – Rendering React in the browser

Figure 1.1 – Rendering React in the browser

This process can be sped up by setting up a development server with Webpack. We'll do this in the final part of this section.

Creating a development server

While working in development mode, every time we make changes to the files in our application, we need to rerun the npm start command. Since this is a bit tedious, we will install another package called webpack-dev-server. This package adds the option to force Webpack to restart every time we make changes to our project files and manages our application files in memory instead of by building the dist directory.

The webpack-dev-server package can be installed with npm:

npm install --save-dev webpack-dev-server

Also, we need to edit the dev script in the package.json file so that it uses webpack-dev-server instead of Webpack. This way, you don't have to recompile and reopen the bundle in the browser after every code change:

{

    "name": "chapter-1",

    "version": "1.0.0",

    "description": "",

    "private": true,

    "scripts": {

-       "start": "webpack –mode development",

+       "start": "webpack serve –mode development",        

        "build": "webpack –mode production"

    },

    "keywords": [],

    "author": "",

    "license": "ISC"

    …

}

The preceding configuration replaces Webpack in the start scripts with webpack-dev-server, which runs Webpack in development mode. This will create a local development server that runs the application, which makes sure that Webpack is restarted every time an update is made to any of your project files.

Run the following command from the command line:

npm start

This will cause the local development server to become active at http://localhost:8080/, and it will refresh every time we make an update to any file in our project.

Now, we've created the basic development environment for our React application, which we'll develop and structure further in the next section of this chapter.

Structuring a project

With the development environment set up, it's time to start creating the single-page application. In the preceding sections, we've already added new directories to the project. But let's recap the current structure of the project, where two of the directories within our project's root directory are important:

  • The first directory is called dist and is where the output from Webpack's bundled version of our application can be found.
  • The second one is called src and includes the source code of our application.

    Note

    Another directory that can be found in the root directory of our project is called node_modules. This is where the source files for every package that we install using npm are placed. It is recommended you don't make any manual changes to files inside this directory.

In the following subsections, we will learn how to structure our React projects. This structure will be used in the rest of the chapters in this book as well.

Creating new components

The official documentation for React doesn't state any preferred approach regarding how to structure our React project, although two common approaches are popular within the community: either structuring your files by feature/page or structuring them by file type.

The single-page application in this chapter will use a hybrid approach, where files are structured by file type first and by feature second. In practice, this means that there will be two types of components: top-level components, which are sometimes called containers, and low-level components, which relate to these top-level components. Creating these components requires that we add the following files and code changes:

  1. The first step to achieving this structure is by creating a new subdirectory of src called components. Inside this directory, create a file called List.js:

    chapter-1

      |- node_modules

      |- package.json

      |- babel.config.json

      |- webpack.config.js

      |- dist

         |- main.js

         |- index.html

      |- public

         |- index.html

      |- src

    +    |- components

    +       |- List.js

         |- index.js

This file will return the component that lists all the information about Rick and Morty:

function List() {

  return <h2>Characters</h2>;

}

export default List;

  1. This component should be included in the entry point of our application so that it's visible. Therefore, we need to include it in the index.js file, inside the src directory, and refer to it:

      import ReactDOM fr'm 'react-dom/client';

    + import List from './components/List';

      function App() {

    -   return <h1>Rick and Morty</h1>;

    +   return (

    +     <div>

    +       <h1>Rick and Morty</h1>

    +       <List />

    +     </div>

    +   );

        };

      // ...

      

If we still have the development server running (if not, execute the npm start command again), we'll see that our application now returns the Characters heading below the title.

  1. The next step is to add a component to the List component, making it a so-called composed component, which is a component that consists of multiple components. This component will be called Character and should also be located in the src subdirectory called components. Inside this directory, create a file called Character.js and add the following code block to it:

    function Character() {

      return <h3>Character</h3>;

    };

    export default Character;

As you have probably guessed from the name of this component, it will be used to return information about a character from Rick and Morty later on.

  1. Now, import this Character component into the List component and return this component after the h2 element by replacing the return function with the following code:

    + import Character from './Character';

      function List() {

    - return <h2>Characters</h2>;

    + return (

    +   <div>

    +     <h2>Characters</h2>

    +     <Character />

    +     <Character />

    +   </div>

    + );

    }

    export default List;

If we visit our application in the browser again at http://localhost:8080/, the words Character will be displayed below the title and heading of the page:

Figure 1.2 – Adding components to React

Figure 1.2 – Adding components to React

From this, we cannot see which components are being rendered in the browser. But luckily, we can open the React Developer Tools plugin in our browser; we'll notice that the application currently consists of multiple stacked components:

<App>

    <List>

        <Character>

In the next part of this section, we will use our knowledge of structuring a React project and create new components to fetch data about Rick and Morty that we want to display in this single-page application.

Retrieving data

With both the development server and the structure for our project set up, it's time to finally add some data to it. For this, we'll be using the Rick and Morty REST API (https://rickandmortyapi.com/documentation/#rest), which provides information about this popular TV show.

Information from APIs can be retrieved in JavaScript using, for example, the fetch method, which is already supported by our browser. This data will be retrieved in the top-level components only, meaning that we should add a fetch function in the List container to retrieve and store that information.

To store the information, we'll be using the built-in state management (https://reactjs.org/docs/state-and-lifecycle.html) in React. Anything stored in the state can be passed down to the low-level components, after which they are called props. A simple example of using state in React is by using the useState Hook, which can be used to store and update variables. Every time these variables change using the update method that is returned by the useState Hook, our component will re-render.

Note

Since the release of version 16.8.0, React has used the concept of Hooks, which are methods supplied by React that let you use its core features without using class components. More information about Hooks can be found in the documentation: https://reactjs.org/docs/hooks-intro.html.

Before adding the logic to retrieve data from the Rick and Morty REST API, let's inspect that API to see what fields will be returned. The base URL for the API is https://rickandmortyapi.com/api.

This URL returns a JSON output with all the possible endpoints for this API, which are all GET requests, meaning read-only, and work over https. From this base URL, we'll be using the /character endpoint to get information about the characters from Rick and Morty. Not all information returned by this endpoint will be used; the following are the fields that we'll actually be using:

  • id (int): The unique identifier of the character
  • name (string): The name of the character
  • origin (object): The object containing the name and the link to the character's origin location
  • image (string): The link to the character's image with the dimensions 300 x 300 px

Before retrieving the data for Rick and Morty, the Character component needs to be prepared to receive this information. To display information about Rick and Morty, we need to add the following lines to the Character component:

- function Character() {

- return <h3>Character</h3>;

+ function Character(character) {

+ return (

+   <div>

+     <h3>{character.name}</h3>

+     <img src={character.image} alt={character.name}

        width='300' />

+     <p>{'Origin: ${character.origin &&

        character.origin.name}'}</p>

+   </div>

+ );

};

export default Character;

Now, the logic to retrieve the data can be implemented by importing useState from React and adding this Hook to the List component, which will contain an empty array as a placeholder for the characters:

+ import { useState } from 'react';

  import Character from './Character';

  function List() {

+   const [characters, setCharacters] = useState([]);

    return (

      // ...

To do the actual data fetching, another Hook should be imported, which is the useEffect Hook. This one can be used to handle side effects, either when the application mounts or when the state or a prop gets updated. This Hook takes two parameters, where the first one is a callback and the second one is an array containing all of the variables this Hook depends on – the so-called dependency array. When any of these dependencies change, the callback for this Hook will be called. When there are no values in this array, the Hook will be called constantly. After the data is fetched from the source, the state will be updated with the results.

In our application, we need to add this Hook and retrieve the data from the API, and we should use an async/await function, since the fetch API returns a promise. After fetching the data, state should be updated by replacing the empty array for data with the character information:

- import { useState } from 'react';

+ import { useEffect, useState } from 'react';

  import Character from './Character';

  function List() {

    const [characters, setCharacters] = useState([]);

+   useEffect(() => {

+     async function fetchData() {

+       const data = await fetch(

          'https://rickandmortyapi.com/api/character');

+       const { results } = await data.json();

+       setCharacters(results);

+     }

+     fetchData();

+   }, [characters.length]);

  return (

    // ...

Inside the useEffect Hook, the new fetchData function will be called, as it's advised to not use an async/await function directly. The Hook is only calling the logic to retrieve the data from the API when the length of the characters state changes. You can extend this logic by also adding a loading state to the application so that the user will know when the data is still being fetched:

  function List() {

+   const [loading, setLoading] = useState(true);

    const [characters, setCharacters] = useState([]);

    useEffect(() => {

      async function fetchData() {

        const data = await fetch(

          'https://rickandmortyapi.com/api/character');

        const { results } = await data.json();

        setCharacters(results);

+       setLoading(false);

      }

      fetchData();

    }, [characters.length]);

  return (

    // ...

Note

The previous method that we used to retrieve information from JSON files using fetch doesn't take into account that the request to this file may fail. If the request fails, the loading state will remain true, meaning that the user will keep seeing the loading indicator. If you want to display an error message when the request doesn't succeed, you'll need to wrap the fetch method inside a try...catch block, which will be shown later on in this book.

To display the character information in the application, we need to pass it to the Character component, where it can ultimately be shown in the Character component that we changed in the first step.

When the data is being retrieved from the API, the loading state is true, so we cannot display the Character component yet. When data fetching is finished, loading will be false, and we can iterate over the character state, return the Character component, and pass the character information as props. This component will also get a key prop, which is required for every component that is rendered within an iteration. Since this value needs to be unique, the id of the character is used, as follows:

  // ...

  return (

    <div>

      <h2>Characters</h2>

-     <Character />

-     <Character />

+     {loading ? (

+       <div>Loading...</div>

+     ) : (

+       characters.map((character) => (

+         <Character

+           key={character.id}

+           name={character.name}

+           origin={character.origin}

+           image={character.image}

+         />

+       ))

+     )}

    </div>

  );

}

export default List;

If we visit our application in the browser again, we'll see that it now shows a list of characters, including some basic information and an image. At this point, our application will look similar to the following screenshot:

Figure 1.3 – Rendering a list of components from the local state

Figure 1.3 – Rendering a list of components from the local state

As you can see, limited styling has been applied to the application, and it's only rendering the information that's been fetched from the API. Styling will be added in the next part of this section using a package called Bootstrap.

Adding styling

Showing just the character information isn't enough. We also need to apply some basic styling to the project. Adding styling to the project is done with the Bootstrap package, which adds styling to our components based on class names.

Bootstrap can be installed from npm using the following and added to devDependencies:

npm install --save-dev bootstrap

Also, import this file into the entry point of our React application, src/index.js, so that we can use the styling throughout the entire application:

  import ReactDOM from 'react-dom/client';

  import List from './containers/List';

+ import 'bootstrap/dist/css/bootstrap.min.css';

  function App() {

    // ...    

Webpack is unable to compile CSS files by itself; we need to add the appropriate loaders to make this happen. We can install these by running the following command:

npm install --save-dev css-loader style-loader

We need to add these packages as a rule to the Webpack configuration:

  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {

    module: {

      rules: [

        {

          test: /.js$/,

          exclude: /node_modules/,

          use: {

            loader: 'babel-loader',

          },

        },

+       {

+         test: /.css$/,

+         use: ['style-loader', 'css-loader'],

+       },

      ],

    },

    plugins: [

      new HtmlWebpackPlugin({

        template: './public/index.html',

        filename: './index.html',

      }),

    ],

  };

Note

The order in which loaders are added is important since css-loader handles the compilation of the CSS file and style-loader adds the compiled CSS files to the React DOM. Webpack reads these settings from right to left, and the CSS needs to be compiled before it's attached to the DOM.

The application should run in the browser correctly now and should have picked up some small styling changes from the default Bootstrap stylesheet. Let's make some changes to the index.js file first and style it as the container for the entire application. We need to change the App component that is rendered to the DOM and wrap the List component with a div container:

  // ...

  function App() {

    return (

-     <div>

+     <div className='container'>

        <h1>Rick and Morty</h1>

        <List />

      </div>

    );

  };

  const root = ReactDOM.createRoot(

    document.getElementById('root'));

  root.render(<App />);

Inside the List component, we need to set the grid to display the Characters components, which display the character information. Wrap the map function in a div element to treat it as a row container for Bootstrap:

  // ...

  return (

    <div>

      <h2>Characters</h2>

+     <div className='row'>

        {loading ? (

          <div>Loading...</div>

        ) : (

          // ...

          ))

        )}

+     </div>

    </div>

  );

}

export default List;

The code for the Character component must also be altered to add styling using Bootstrap; you can replace the current contents of that file with the following:

function Character(character) {

  return (

    <div className='col-3'>

      <div className='card'>

        <img

          src={character.image}

          alt={character.name}

          className='card-img-top'

        />

        <div className='card-body'>

          <h3 className='card-title'>{character.name}</h3>

          <p>{'Origin: ${character.origin &&

            character.origin.name}'}</p>

        </div>

      </div>

    </div>

  );

};

export default Character;

This lets us use the Bootstrap container layout with a column size of 3 (https://getbootstrap.com/docs/5.0/layout/columns/) and style the Character component as a Bootstrap card component (https://getbootstrap.com/docs/5.0/components/card/).

To add the finishing touches, open the index.js file and insert the following code to add a header that will be placed above our list of Rick and Morty characters in the application:

  // ...

  function App() {

    return (

      <div className='container'>

-       <h1>Rick and Morty</h1>

+       <nav className='navbar sticky-top navbar-light

          bg-dark'>

+         <h1 className='navbar-brand text-light'>

            Rick and Morty</h1>

+       </nav>

        <List />

      </div>

        );

  // ...

  

After making sure that the development server is running, we'll see that the application has had styling applied through Bootstrap, which will make it look as follows in the browser:

Figure 1.4 – Our application styled with Bootstrap

Figure 1.4 – Our application styled with Bootstrap

The style rules from Bootstrap have been applied to our application, making it look far more complete than it did before. In the final part of this section, we'll add the ESLint package to the project, which will make maintaining our code easier by synchronizing patterns across the project.

Adding ESLint

Finally, we will add ESLint to the project to make sure our code meets certain standards – for instance, that our code follows the correct JavaScript patterns.

Install ESLint from npm by running the following command:

npm install --save-dev eslint eslint-webpack-plugin eslint-plugin-react

The first package, called eslint, is the core package and helps us identify any potentially problematic patterns in our JavaScript code. eslint-webpack-plugin is a package that is used by Webpack to run ESLint every time we update our code. Finally, eslint-plugin-react adds specific rules to ESLint for React applications.

To configure ESLint, we need to create a file called .eslintrc in the project's root directory and add the following code to it:

{

  "env": {

    "browser": true,

    "node": true,

    "es6": true

  },

  "parserOptions": {

    "ecmaVersion": 2020,

    "sourceType": "module"

  },

  "plugins": ["react"],

  "extends": ["eslint:recommended",

              "plugin:react/recommended"],

  "rules": {

    "react/react-in-jsx-scope": "off"

  }

}  

The env field sets the actual environment our code will run in and will use es6 functions in it, while the parserOptions field adds extra configuration for using jsx and modern JavaScript. Where things get interesting, however, is the plugins field, which is where we specify that our code uses react as a framework. The extends field is where the recommended settings for eslint are used, as well as framework-specific settings for React. Also, the rules field contains a rule to disable the notification about React not being imported, as this is no longer required in React 18.

Note

We can run the eslint --init command to create custom settings, but using the preceding settings is recommended so that we ensure the stability of our React code.

If we look at our command line or browser, we will see no errors. However, we have to add the eslint-webpack-plugin package to the Webpack configuration. In the webpack.config.js file, you need to import this package and add it as a plugin to the configuration:

  const HtmlWebpackPlugin = require('html-webpack-plugin');

+ const ESLintPlugin = require('eslint-webpack-plugin');

  module.exports = {

    // ...

    plugins: [

      new HtmlWebpackPlugin({

        template: './public/index.html',

        filename: './index.html',

      }),

+     new ESLintPlugin(),

    ],

  };

By restarting the development server, Webpack will now use ESLint to check whether our JavaScript code complies with the configuration of ESLint. In our command line (or the Console tab in the browser), any misuse of React (or JavaScript) functionalities will be shown.

Congratulations! You have created a basic React application from scratch using React, ReactDOM, Webpack, Babel, and ESLint.

Summary

In this chapter, you've created a single-page application for React from scratch and learned about core React concepts. This chapter started with you creating a new project with Webpack and Babel. These libraries help you compile and run your JavaScript and React code in a browser with minimal setup. Then, we described how to structure a React application, and this structure will be used throughout this book. Also, you learned about state management and data fetching using React Hooks and basic styling with Bootstrap. The principles that were applied provided you with the basics from which to create React applications from nothing and structure them in a scalable way.

If you've worked with React before, then these concepts probably weren't that hard to grasp. If you haven't, then don't worry if some concepts felt strange to you. The upcoming chapters will build upon the features that you used in this chapter, giving you enough time to fully understand them.

The project you'll build in the next chapter will focus on creating reusable React components with more advanced styling. This will be available offline, since it will be set up as a Progressive Web Application (PWA).

Further reading

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.86.138