React 02 : Hello World

Introduction

This is the second article of our 'React with me' series. In this series, we are learning React.js, a powerful JavaScript library for making dynamic user interfaces.

Recap

Earlier in the series, we discussed how to set up our React development environment. If you have not yet set up your React development environment, feel free to check out that article here.

Overview

In this article, we will take our first step towards building a React application with the classic example, "Hello World!" We will start learning about components in React and create custom components as we go.

Directory structure

When we ended our last article, our directory structure was looking something like this.

We have a 'src' directory and a 'public' directory, along with several files in our root directory. Let's go through them one by one.

  1. .gitignore: This is used to ignore certain files and directories when we push our code to GitHub.

  2. eslint.config.js: This is the configuration file of esLint, a tool that helps identify and fix issues in your JavaScript code.

  3. index.html: This is the index.html file of our React application. It has one div element in which our application is loaded.

  4. packege.json: This is the JSON (JavaScript Object Notation) file that contains important project information, for managing dependencies, scripts, metadata, and other essential project details.

  5. Readme.md: This file contains the description and information about our project. It is used to communicate important information about your project.

  6. vite.config.js: This is the vite configuration file, where you can define various settings and configurations for Vite to optimize your development and build process.

Understanding package.json

We don't need to worry about any of these now, but let's take a quick look at 'package.json'

{
  "name": "demo-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@eslint/js": "^9.8.0",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "eslint": "^9.8.0",
    "eslint-plugin-react": "^7.35.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.9",
    "globals": "^15.9.0",
    "vite": "^5.4.0"
  }
}

We have a few scripts, two dependencies ('react' and 'react-dom'), and several dev dependencies. We don't need to worry about the dev dependencies; they are just there to help us during development. I want to highlight the dependencies 'react' and 'react-dom' because we will be using them later in the article.

'public' and 'src' directories

Now let us look at the files inside our 'public' and 'src' directories.

  1. Public directory: It has an SVG file inside it, 'vite.svg'. The public directory is used to store static assets like images that can be accessed by the browser directly.

  2. Src directory: This is the src (short for 'source') directory, where we store all the source code files of our application, like the JavaScript and CSS files.

    In our 'src' directory, we have the following files: App.css, App.jsx, index.css, and main.jsx, we also have a directory in which we have 'react.svg'. You might ask, "We are familiar with the CSS files, but what is this 'jsx'?" We will look into that later in this article.

Let's now open these files and see what's inside them.

  1. App.css

     #root {
       max-width: 1280px;
       margin: 0 auto;
       padding: 2rem;
       text-align: center;
     }
    
     .logo {
       height: 6em;
       padding: 1.5em;
       will-change: filter;
       transition: filter 300ms;
     }
     .logo:hover {
       filter: drop-shadow(0 0 2em #646cffaa);
     }
     .logo.react:hover {
       filter: drop-shadow(0 0 2em #61dafbaa);
     }
    
     @keyframes logo-spin {
       from {
         transform: rotate(0deg);
       }
       to {
         transform: rotate(360deg);
       }
     }
    
     @media (prefers-reduced-motion: no-preference) {
       a:nth-of-type(2) .logo {
         animation: logo-spin infinite 20s linear;
       }
     }
    
     .card {
       padding: 2em;
     }
    
     .read-the-docs {
       color: #888;
     }
    

    App.css: On analyzing the CSS, we can see that it is pretty readable and straightforward. It contains a few id's and classes that style the main elements of our application, keyframes to animate the logo, and media query that checks if the user does not prefer reduced motion. It applies the logo spin animation to the second logo element.

  2. index.css

     :root {
       font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
       line-height: 1.5;
       font-weight: 400;
    
       color-scheme: light dark;
       color: rgba(255, 255, 255, 0.87);
       background-color: #242424;
    
       font-synthesis: none;
       text-rendering: optimizeLegibility;
       -webkit-font-smoothing: antialiased;
       -moz-osx-font-smoothing: grayscale;
     }
    
     a {
       font-weight: 500;
       color: #646cff;
       text-decoration: inherit;
     }
     a:hover {
       color: #535bf2;
     }
    
     body {
       margin: 0;
       display: flex;
       place-items: center;
       min-width: 320px;
       min-height: 100vh;
     }
    
     h1 {
       font-size: 3.2em;
       line-height: 1.1;
     }
    
     button {
       border-radius: 8px;
       border: 1px solid transparent;
       padding: 0.6em 1.2em;
       font-size: 1em;
       font-weight: 500;
       font-family: inherit;
       background-color: #1a1a1a;
       cursor: pointer;
       transition: border-color 0.25s;
     }
     button:hover {
       border-color: #646cff;
     }
     button:focus,
     button:focus-visible {
       outline: 4px auto -webkit-focus-ring-color;
     }
    
     @media (prefers-color-scheme: light) {
       :root {
         color: #213547;
         background-color: #ffffff;
       }
       a:hover {
         color: #747bff;
       }
       button {
         background-color: #f9f9f9;
       }
     }
    

    index.css: In this css file we have declared some variables, and we have some general styling for elements like buttons, a tags, h1 tags and body.

App.jsx

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {
  const [count, setCount] = useState(0)

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.jsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App

App.jsx: This is our App.jsx file. Things here might seem a bit overwhelming at first, but don't worry. Let's look at it one step at a time.

Understanding JSX

Let us first understand what is JSX. JSX stands for JavaScript XML is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file, which React then converts to real DOM elements. JSX is similar to HTML but not exactly the same.
Now back to App.jsx.
In the first 4 lines we are importing a few things, and these are:

  1. Firstly, we are importing useState from React. We haven't covered Hooks yet, so don't worry about it. If it's there, let it be, and let's move on.

  2. Second, we are importing reactLogo from './assets/react.svg'. Remember? We had an assets directory that had 'react.svg'. Well, we are importing that SVG here.

  3. Third, we are importing viteLogo from '/vite.svg'. Pretty self-explanatory.

  4. Lastly, we are importing App.css. We wrote some CSS, so to use it, we need to import it.

Next we have a function named App(). It has some code in it. Well if we see it has two parts.

  1. There is a const declaration, and we are assigning the useState hook to what looks like an array. We haven't discussed hooks yet, so let's ignore this for now and move on. We will discuss hooks in our later articles, but not now.

  2. We are also returning something. Let's see what we are returning. This looks like HTML to me. Well, that's because it is HTML. This isn't new; we've been returning HTML in JavaScript for ages.
    Taking a quick look, we see we are using the classes from our CSS files. So now we know why we imported the App.css file.

Lastly we are exporting the function.

Well, if we think about it, App.jsx is not that complex. We have a few import statements, a function that returns HTML, and then we export the function.

But if we are exporting the function, where are we using it? Well if you remember We also had a 'main.jsx' file.

  1. main.jsx

     import { StrictMode } from 'react'
     import { createRoot } from 'react-dom/client'
     import App from './App.jsx'
     import './index.css'
    
     createRoot(document.getElementById('root')).render(
       <StrictMode>
         <App />
       </StrictMode>,
     )
    

    Let's again break this down into two parts: import statements and createRoot.

    1. There are four import statements in this file.

      1. StrictMode from 'react: We use StrictMode to enable additional development behaviors and warnings for the component tree inside:

        Strict Mode enables the following development-only behaviors:

        • Your components will re-render an extra time to find bugs caused by impure rendering.

        • Your components will re-run Effects an extra time to find bugs caused by missing Effect cleanup.

        • Your components will be checked for usage of depreciated APIs.

      2. createRoot from 'react-dom/client': createRoot is a method provided by 'react-dom/client' package.

      3. App from 'App.jsx': We are importing the App function from App.jsx file.

      4. Lastly we are importing './index.css'.

  2. createRoot: It is used to initialize and manage the root of a React application. The 'root' of a React application is the 'div' in the 'index.html' file with the id 'root'. It doesn't have to be named 'root'; it can be anything, but by convention, we name it 'root'. It is where our React application gets rendered.

    After we have our root, we use the render method, to render our react component.
    You might say, "But we never made a component!" Actually, we did! Just look at how the App is being called in the render method, that is not how we call a function.

     <App />
    

    Actually, we can call App just like any other function App() But it's not a good practice, It is supposed to be JSX, and by convention, we call the component like this <App /> .

Components

The App.jsx is a component, the function App inside it is responsible for what this component renders. Components are the building blocks of our UI. They allow us to break down the UI into smaller, reusable pieces, making our code more modular and easier to manage.

Now that we know what these files in our React project do, let's start with our "Hello World!" example.

Project Cleanup

Let's first clean our React project so that we have a blank slate to write "Hello World!".

This is what our project's directory looks right now, let's get rid of the files that we do not need.

eslint.config.js  package.json       README.md
index.html        package-lock.json  vite.config.js

node_modules:...

public:
vite.svg

src:
App.css  App.jsx  assets  index.css  main.jsx
  1. We won't need any SVG files so delete the 'vite.svg' and 'src/assets/react.svg'.

  2. We don't need any styling so delete the css files, 'App.css' and 'index.css'.

Now that we have cleaned our project directory let us clean our App.jsx and main.jsx files.

App.jsx

Remove all the import statements, as we do not have any SVGs and we are not using hooks. After removing them lets clean our function. We are not using useState so we dont need const [count, setCount] = useState(0), and we also don't need to return all that HTML. After doing that our App.jsx will look something like this.

function App() {
  return (

  )
}

export default App

We don't need to change anything in our main.jsx file.
When we check our browser, we now see a completely blank screen.

"Hello World!" Example

Let us now change our App.jsx so that it renders "Hello World!" in our root.
Put an h1 tag inside the return statement of the App function.

function App() {
  return (
    <h1>Hello World!</h1>
  )
}

export default App

When we look at our browser, we will see that our Hello World! is successfully rendered.

What we learned

So this was our article, What did we learn today?

  1. We explored our React project directory, understanding the purpose of each file and the code within them.

  2. We learned how components are made.

  3. We also learned how to render a component in our project root.

Conclusion

If you have any questions regarding any of the steps, feel free to reach out to me on LinkedIn or Twitter. This demo-project is on github.

Acknowledgements

This article was written by referencing Chai aur React series from Chai aur Code YouTube channel, By Hitesh Choudhary.

Next Step

In the next article, we will dive deeper into React's flow and structure.

If you found this guide helpful, don’t forget to share it with fellow developers who are just starting their React journey.