Skip to main content

Your First React App with Vite (Part 2) #08

📖 Introduction

Following our successful scaffolding of a new React project in Your First React App with Vite (Part 1), this article, Part 2, will take a deeper dive into the initial project structure generated by Vite. We'll explore the key files and folders, focusing on how your "Hello World" application is rendered from index.html through main.jsx to App.jsx. Understanding this foundational flow is crucial for building and organizing your React applications effectively.


📚 Prerequisites

Before we begin, please ensure you have a solid grasp of the following concepts:

  • Article 7 Concepts: You should have successfully created and run your first Vite React application.
  • HTML Structure: Basic understanding of HTML elements and how a browser renders them.
  • JavaScript Modules: Familiarity with import and export statements in JavaScript.
  • React Components: A basic understanding of what a React component is (as covered in Article 03).

🎯 Article Outline: What You'll Master

In this article, you will learn:

  • The Role of index.html: How the main HTML file serves as the entry point.
  • main.jsx Explained: The JavaScript entry point and its role in rendering the React app.
  • App.jsx Deep Dive: Understanding the root React component.
  • The src Directory: A closer look at where your application code lives.
  • Connecting the Dots: Tracing the rendering flow from HTML to your React components.

🧠 Section 1: The Entry Points: index.html and main.jsx

Every web application needs an entry point – a starting file that the browser loads. In a Vite React application, this process involves index.html and main.jsx (or main.tsx for TypeScript projects).

1.1 - index.html: The HTML Shell

Unlike older React setups (like Create React App) where index.html was often tucked away in a public folder and treated as a static asset, Vite treats index.html as a source file and a central part of your module graph.

Open the index.html file in your project root:

<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div> <!-- This is where your React app will be mounted! -->
<script type="module" src="/src/main.jsx"></script> <!-- Your JavaScript entry point -->
</body>
</html>

Key Observations:

  • <div id="root"></div>: This is the most important line for your React application. This div acts as the "mount point" or "root element" where your entire React application will be injected and rendered by JavaScript. When React takes control, everything inside this div will be managed by React.
  • <script type="module" src="/src/main.jsx"></script>: This line is the actual entry point for your JavaScript code.
    • type="module": This tells the browser to treat main.jsx as an ES Module, allowing you to use import and export statements. Vite leverages this native browser feature for its speed.
    • src="/src/main.jsx": This specifies the path to your main JavaScript file. Notice it points directly to a file inside the src directory, highlighting Vite's direct serving approach.

In essence, index.html provides the basic HTML structure and a designated spot (#root) for your React application to live, along with the script tag that kicks off your JavaScript.

1.2 - main.jsx: The JavaScript Orchestrator

The main.jsx file is the JavaScript entry point that Vite loads. Its primary responsibility is to initialize your React application and "mount" it to the root element in index.html.

Open the src/main.jsx file:

// src/main.jsx
import React from 'react'; // Imports the React library
import ReactDOM from 'react-dom/client'; // Imports ReactDOM for client-side rendering
import App from './App.jsx'; // Imports your main App component
import './index.css'; // Imports global CSS styles

// Create a React root and render your App component into the DOM
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App /> {/* This is your main application component */}
</React.StrictMode>,
);

Key Lines and Their Roles:

  • import React from 'react';: Imports the core React library. As discussed in Article 03, this is necessary for JSX to work.
  • import ReactDOM from 'react-dom/client';: Imports ReactDOM from react-dom/client. ReactDOM is the package that provides DOM-specific methods for React. createRoot is the modern way to create a root for your React application, replacing the older ReactDOM.render().
  • import App from './App.jsx';: This line imports your main application component, App, from App.jsx. This is where your custom UI logic will reside.
  • import './index.css';: This imports the global CSS file, applying styles to your entire application.
  • ReactDOM.createRoot(document.getElementById('root')): This line finds the div element in index.html with the ID root and creates a React "root" for your application. This root is where React will manage the DOM updates.
  • .render(<React.StrictMode><App /></React.StrictMode>): This tells React to render your App component inside the created root.
    • <React.StrictMode>: This is a special component that helps you find potential problems in your application during development. It activates additional checks and warnings for its descendants. It does not render any visible UI.
    • <App />: This is your main React component, which will render the "Hello World" content.

In summary, main.jsx acts as the bridge between your HTML file and your React components, initiating the rendering process.


🛠️ Section 3: The src Directory and App.jsx

The src directory is where the heart of your React application lives. It contains all your components, styles, and assets.

3.1 - The src Directory Structure

src/
├── assets/
│ └── react.svg # Static assets like images, SVGs
├── App.css # CSS scoped to the App component (or global if imported in App.jsx)
├── App.jsx # Your main React component
├── index.css # Global CSS styles, imported in main.jsx
└── main.jsx # The JavaScript entry point, renders App.jsx
  • assets/: This folder is typically used for static assets like images, icons, or fonts that your components might use.
  • App.css: This file contains CSS rules specifically for the App component. It's imported directly into App.jsx.
  • index.css: This file contains global CSS rules that apply to your entire application. It's imported in main.jsx to ensure it's loaded early.
  • App.jsx: This is your primary React component. When you first create a Vite React app, this file contains the default "Hello World" content.

3.2 - App.jsx: Your Root Component

The App.jsx file contains the App component, which is the root of your component tree. All other components you create will typically be nested within or imported into this App component.

Open the src/App.jsx file:

// src/App.jsx
import { useState } from 'react'; // Import the useState Hook
import reactLogo from './assets/react.svg'; // Import an SVG asset
import viteLogo from '/vite.svg'; // Import another SVG asset (from public folder)
import './App.css'; // Import CSS specific to this component

function App() {
const [count, setCount] = useState(0); // Declare a state variable

return (
<> {/* React Fragment: allows returning multiple elements without an extra DOM node */}
<div>
<a href="https://vitejs.dev" target="_blank" rel="noopener noreferrer">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank" rel="noopener noreferrer">
<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;

Key Elements in App.jsx:

  • import { useState } from 'react';: This imports the useState Hook, a fundamental React feature for managing component state (which we'll cover in detail in later articles).
  • import reactLogo from './assets/react.svg'; and import viteLogo from '/vite.svg';: These lines demonstrate how to import static assets (like images) into your components. Vite handles these imports efficiently. Notice the difference in paths: ./assets/react.svg is relative to the current file, while /vite.svg refers to an asset in the public folder (relative to the project root).
  • import './App.css';: Imports the CSS file specific to this component.
  • function App() { ... }: Defines the functional App component.
  • const [count, setCount] = useState(0);: Initializes a state variable count with an initial value of 0.
  • return (<> ... </>): The component returns JSX. The <> and </> are a React Fragment, which allows you to return multiple JSX elements without adding an extra div (or other wrapper element) to the actual DOM.
  • JSX Structure: The returned JSX contains various HTML elements (div, a, img, h1, button, p) and displays dynamic content (count).
  • onClick={() => setCount((count) => count + 1)}: This is an event handler. When the button is clicked, it calls the setCount function to update the count state, which triggers a re-render of the component.

🚀 Section 4: Tracing the Rendering Flow: From HTML to UI

Let's put it all together and trace how your "Hello World" application goes from files on your disk to a rendered UI in your browser.

  1. Browser Loads index.html: When you run npm run dev, Vite serves your index.html file.
  2. index.html Loads main.jsx: The <script type="module" src="/src/main.jsx"></script> tag in index.html tells the browser to load and execute main.jsx as an ES Module.
  3. main.jsx Initializes React:
    • It imports React and ReactDOM.
    • It imports your App component (import App from './App.jsx';).
    • ReactDOM.createRoot(document.getElementById('root')).render(<App />) finds the #root div in index.html and tells React to render the App component inside it.
  4. App.jsx Renders UI:
    • The App component's function is executed.
    • It uses the useState Hook to manage its internal count state.
    • It returns the JSX that describes the UI (logos, heading, button, paragraph).
  5. React's Virtual DOM in Action:
    • React takes the JSX returned by App.jsx and builds a Virtual DOM tree.
    • It efficiently compares this VDOM with the previous one (if any) and calculates the minimal changes needed.
    • These changes are then applied to the Real DOM in the browser.
  6. Browser Displays UI: The browser updates the visual display, and you see your "Vite + React" page with the interactive counter.

When you click the button, the setCount function updates the count state. This triggers React to re-render the App component, create a new Virtual DOM, diff it, and apply only the change to the count display in the Real DOM, making the UI update seamlessly.


✨ Section 5: Best Practices and Customization

Best Practices:

  • Modular Components: As your application grows, break down App.jsx into smaller, more focused components (e.g., Header, Sidebar, ProductList). Import and compose them within App.jsx.
  • Clear Naming: Use descriptive names for your files and components.
  • Consistent Styling: Decide on a styling approach (e.g., global CSS, CSS Modules, CSS-in-JS) and stick to it.
  • Understand vite.config.js: As your project grows, you'll likely need to customize Vite's behavior (e.g., adding plugins, setting up path aliases). Familiarize yourself with vite.config.js.

Customization Examples:

  • Changing the Title: Edit the <title> tag in index.html.
  • Modifying the Root Component: Change the content of App.jsx to build your own UI.
  • Adding Global Styles: Modify index.css or import other global stylesheets into main.jsx.

💡 Conclusion & Key Takeaways

You've now completed your deep dive into the structure of your first React application built with Vite! You understand the roles of index.html, main.jsx, and App.jsx, and how they work together to render your UI. This foundational knowledge is critical for confidently navigating and building more complex React projects.

Let's summarize the key takeaways:

  • index.html: The initial HTML shell and mount point (#root) for your React app.
  • main.jsx: The JavaScript entry point that initializes React and renders your root component into the DOM.
  • App.jsx: Your primary React component, where you'll build and compose your application's UI.
  • src Directory: Contains all your application's source code, including components, styles, and assets.
  • Rendering Flow: Browser loads index.html -> main.jsx runs -> React mounts App.jsx to #root -> React manages DOM updates.

Challenge Yourself: Modify your App.jsx file to remove the default Vite and React logos and the counter. Instead, try to render a simple "Hello, [Your Name]!" message using a new functional component that you create in a separate file (e.g., src/components/MyGreeting.jsx) and import into App.jsx.


➡️ Next Steps

Congratulations on completing the first series of articles! You now have a solid understanding of what React is, its core concepts, and how to set up and run your first application. In the next series, "Understanding Components", we will delve deeper into the world of React components, exploring their types, anatomy, and how to effectively use them to build modular and reusable UIs.

Thank you for your dedication. Stay curious, and happy coding!


glossary

  • index.html: The main HTML file of a web application, serving as the initial page loaded by the browser. In Vite, it's also a source file.
  • main.jsx (or main.tsx): The primary JavaScript/TypeScript entry point of a React application, responsible for importing the root React component and rendering it into the DOM.
  • App.jsx (or App.tsx): The root React component of an application, typically where other components are imported and composed to build the main UI.
  • src Directory: The source directory in a web project where most of the application's editable code (components, styles, assets) resides.
  • Mount Point (or Root Element): The specific HTML DOM element (e.g., <div id="root"></div>) into which a JavaScript framework (like React) injects and manages its UI.
  • ReactDOM.createRoot(): The modern React 18+ API for creating a root to display React components inside a browser DOM node.
  • React.StrictMode: A development-only tool in React that helps identify potential problems in an application by activating additional checks and warnings.
  • React Fragment (<>...</>): A feature in React that lets you group a list of children without adding extra nodes to the DOM.
  • Static Assets: Files (like images, fonts, or plain CSS) that are served directly by the web server without being processed or transformed by a build tool.

Further Reading