coderain guide

Building Your First React Frontend from Scratch

React has revolutionized frontend development with its component-based architecture, reusability, and efficient rendering. Whether you’re new to web development or transitioning from vanilla JavaScript, building your first React frontend is an exciting step toward creating dynamic, interactive applications. In this guide, we’ll walk through the entire process—from setting up your development environment to deploying a functional React app. You’ll learn core concepts like **components**, **JSX**, **props**, **state**, and even basic routing and data fetching. By the end, you’ll have a fully working React application and the confidence to expand on it!

Table of Contents

  1. Prerequisites
  2. Setting Up Your Development Environment
  3. Understanding the React Project Structure
  4. Your First React Component: JSX and Rendering
  5. Components and Props: Reusability in Action
  6. State Management with useState
  7. Handling Events in React
  8. Styling Your React App
  9. Adding Routing with React Router
  10. Fetching Data from an API
  11. Testing Your React App
  12. Deploying Your React App
  13. Conclusion
  14. References

Prerequisites

Before diving in, ensure you have:

  • Basic knowledge of HTML, CSS, and JavaScript: React builds on these fundamentals.
  • Node.js and npm: React tools rely on Node.js (a JavaScript runtime) and npm (Node Package Manager). Download them from nodejs.org (LTS version recommended).
  • Familiarity with ES6+ JavaScript: Concepts like arrow functions (() => {}), destructuring (const { name } = user), and template literals (`Hello ${name}`) will simplify your React code.

Setting Up Your Development Environment

The easiest way to start a React project is with Create React App (CRA), a toolchain maintained by Facebook that sets up a modern React environment with zero configuration.

Step 1: Install Create React App

Open your terminal and run:

npx create-react-app my-first-react-app  
  • npx (Node Package Runner) temporarily installs CRA to create your project, so you don’t need to install it globally.
  • my-first-react-app is your project name (feel free to change it!).

Step 2: Navigate to Your Project and Start the Dev Server

cd my-first-react-app  
npm start  

This will launch a development server at http://localhost:3000. You’ll see a default React welcome page—congrats, your React app is running!

Understanding the React Project Structure

Let’s explore the key files and folders in your new project:

my-first-react-app/  
├── node_modules/       # Dependencies (auto-generated)  
├── public/             # Static files  
│   ├── index.html      # HTML entry point (React renders here)  
│   ├── favicon.ico     # Icon for your app  
│   └── manifest.json   # Metadata for progressive web apps (PWA)  
├── src/                # Source code (where you’ll work!)  
│   ├── App.css         # Styles for App component  
│   ├── App.js          # Root component  
│   ├── App.test.js     # Tests for App component  
│   ├── index.css       # Global styles  
│   ├── index.js        # Renders React to the DOM  
│   ├── logo.svg        # Default React logo  
│   └── reportWebVitals.js # Performance tracking (optional)  
├── .gitignore          # Files to ignore in Git  
├── package.json        # Project metadata and scripts  
└── README.md           # Project documentation  

Key Files:

  • public/index.html: The only HTML file. React injects your app into the <div id="root"></div> element here.
  • src/index.js: The JavaScript entry point. It imports React, ReactDOM, and your App component, then renders App into the DOM:
    import React from 'react';  
    import ReactDOM from 'react-dom/client';  
    import './index.css';  
    import App from './App';  
    
    const root = ReactDOM.createRoot(document.getElementById('root'));  
    root.render(  
      <React.StrictMode>  
        <App />  
      </React.StrictMode>  
    );  
  • src/App.js: The root component of your app (we’ll modify this heavily!).

Your First React Component: JSX and Rendering

React apps are built with components—reusable, self-contained pieces of UI. Components can be functions or classes; we’ll focus on functional components (the modern, preferred approach).

What is JSX?

JSX (JavaScript XML) is a syntax extension for JavaScript that lets you write HTML-like code within JavaScript. It’s not HTML, but a way to describe what the UI should look like.

Example JSX:

const element = <h1>Hello, React!</h1>;  

JSX is transpiled (converted) to regular JavaScript by tools like Babel, which is included in CRA.

Modifying the App Component

Let’s replace the default App.js with a simpler component. Open src/App.js and update it:

import './App.css';  

function App() {  
  return (  
    <div className="App">  
      <h1>Welcome to My First React App! 🚀</h1>  
      <p>This is a simple React frontend built from scratch.</p>  
    </div>  
  );  
}  

export default App;  
  • function App(): This is a functional component (a JavaScript function that returns JSX).
  • className: In JSX, use className instead of class (since class is a reserved keyword in JavaScript).
  • Save the file—the dev server will auto-reload, and you’ll see your new content at http://localhost:3000.

Components and Props: Reusability in Action

Components become powerful when you can reuse them with different data. Props (short for “properties”) let you pass data from a parent component to a child component.

Step 1: Create a Reusable Component

Let’s build a UserCard component that displays a user’s name, role, and avatar. Create a new folder src/components and add UserCard.js:

// src/components/UserCard.js  
function UserCard(props) {  
  return (  
    <div className="user-card">  
      <img src={props.avatar} alt={props.name} />  
      <h3>{props.name}</h3>  
      <p>Role: {props.role}</p>  
    </div>  
  );  
}  

export default UserCard;  

Here, props is an object containing the data passed to UserCard.

Step 2: Use the Component with Props

Now, import UserCard into App.js and use it with different props:

import './App.css';  
import UserCard from './components/UserCard';  

function App() {  
  return (  
    <div className="App">  
      <h1>Our Team 👥</h1>  
      <div className="user-cards">  
        <UserCard  
          name="Alice Smith"  
          role="Frontend Developer"  
          avatar="https://i.pravatar.cc/150?img=1"  
        />  
        <UserCard  
          name="Bob Johnson"  
          role="Backend Developer"  
          avatar="https://i.pravatar.cc/150?img=2"  
        />  
      </div>  
    </div>  
  );  
}  

export default App;  

Step 3: Add Styling (Optional)

To make the cards look better, add styles to src/App.css:

/* src/App.css */  
.App {  
  max-width: 800px;  
  margin: 0 auto;  
  padding: 2rem;  
  text-align: center;  
}  

.user-cards {  
  display: grid;  
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));  
  gap: 2rem;  
  margin-top: 2rem;  
}  

.user-card {  
  border: 1px solid #e0e0e0;  
  border-radius: 8px;  
  padding: 1.5rem;  
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);  
}  

.user-card img {  
  width: 100px;  
  height: 100px;  
  border-radius: 50%;  
  object-fit: cover;  
}  

Now your app will display two styled user cards with unique data!

State Management with useState

State is data that changes over time and affects your component’s rendering. Unlike props (which are passed from parents and immutable), state is managed inside a component and can be updated.

React provides hooks—special functions—to add state to functional components. The most basic hook is useState.

Example: Building a Counter

Let’s create a Counter component that increments a number when a button is clicked.

  1. Create src/components/Counter.js:
import { useState } from 'react';  

function Counter() {  
  // Initialize state: [currentState, setState] = useState(initialValue)  
  const [count, setCount] = useState(0);  

  return (  
    <div className="counter">  
      <h2>Counter: {count}</h2>  
      <button onClick={() => setCount(count + 1)}>Increment</button>  
    </div>  
  );  
}  

export default Counter;  
  • useState(0): Initializes the count state to 0.
  • setCount: A function to update count (never modify state directly, e.g., count++).
  • onClick: React event handler (note the camelCase: onClick instead of onclick).
  1. Import Counter into App.js and use it:
import './App.css';  
import UserCard from './components/UserCard';  
import Counter from './components/Counter';  

function App() {  
  return (  
    <div className="App">  
      <h1>My React App Features 🎯</h1>  
      <Counter />  
      {/* ... UserCard code ... */}  
    </div>  
  );  
}  

Click the “Increment” button—the counter will update!

Handling Events in React

React events (like onClick, onChange, onSubmit) work similarly to HTML events but with camelCase syntax and require functions as handlers.

Example: Form Input with onChange

Let’s add a form that updates state as the user types. Create src/components/SearchBar.js:

import { useState } from 'react';  

function SearchBar() {  
  const [searchTerm, setSearchTerm] = useState('');  

  const handleChange = (e) => {  
    setSearchTerm(e.target.value); // e.target.value is the input text  
  };  

  return (  
    <div className="search-bar">  
      <input  
        type="text"  
        placeholder="Search..."  
        value={searchTerm}  
        onChange={handleChange}  
      />  
      <p>You searched for: {searchTerm}</p>  
    </div>  
  );  
}  

export default SearchBar;  
  • value={searchTerm}: Binds the input’s value to the searchTerm state (controlled component).
  • onChange={handleChange}: Updates searchTerm whenever the input changes.

Styling Your React App

React offers multiple styling approaches. Here are the most common:

1. Inline Styles

Quick for small components, but not ideal for large apps:

<div style={{ color: 'blue', fontSize: '20px' }}>Hello</div>  

2. CSS Files

Global styles (e.g., src/index.css) or component-specific styles (e.g., UserCard.css). Import the CSS file into your component:

import './UserCard.css';  

3. CSS Modules (Scoped Styles)

To avoid style conflicts, use CSS Modules (built into CRA). Rename UserCard.css to UserCard.module.css:

/* UserCard.module.css */  
.userCard {  
  border: 1px solid #e0e0e0;  
  /* ... */  
}  

Import and use it in UserCard.js:

import styles from './UserCard.module.css';  

function UserCard(props) {  
  return <div className={styles.userCard}>...</div>;  
}  

Class names are scoped to the component (e.g., userCard becomes UserCard_userCard__abc123).

Adding Routing with React Router

Single-Page Applications (SPAs) like React apps use client-side routing to navigate without reloading the page. Use react-router-dom for this.

Step 1: Install React Router

npm install react-router-dom  

Step 2: Set Up Routes

Create src/pages for route components: Home.js, About.js, Contact.js.

Home.js:

function Home() {  
  return <h1>Home Page 🏠</h1>;  
}  

export default Home;  

About.js:

function About() {  
  return <h1>About Us ℹ️</h1>;  
}  

export default About;  

Step 3: Configure Routing in App.js

Update App.js to use React Router:

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';  
import Home from './pages/Home';  
import About from './pages/About';  
import Contact from './pages/Contact';  
import './App.css';  

function App() {  
  return (  
    <Router>  
      <nav>  
        <Link to="/">Home</Link> |  
        <Link to="/about">About</Link> |  
        <Link to="/contact">Contact</Link>  
      </nav>  
      <Routes>  
        <Route path="/" element={<Home />} />  
        <Route path="/about" element={<About />} />  
        <Route path="/contact" element={<Contact />} />  
      </Routes>  
    </Router>  
  );  
}  

export default App;  
  • Router: Wraps your app to enable routing.
  • Link: Replaces <a> tags for client-side navigation.
  • Routes and Route: Define which component to render for each URL path.

Fetching Data from an API

Most apps need to fetch data from a backend API. Use the fetch API or libraries like axios with React’s useEffect hook (runs side effects, like data fetching).

Example: Fetching Users from JSONPlaceholder

JSONPlaceholder is a free fake API for testing. Let’s fetch and display a list of users.

Create src/components/UserList.js:

import { useState, useEffect } from 'react';  

function UserList() {  
  const [users, setUsers] = useState([]);  
  const [loading, setLoading] = useState(true);  
  const [error, setError] = useState(null);  

  useEffect(() => {  
    // Fetch data when the component mounts  
    fetch('https://jsonplaceholder.typicode.com/users')  
      .then((res) => {  
        if (!res.ok) throw new Error('Failed to fetch users');  
        return res.json();  
      })  
      .then((data) => {  
        setUsers(data);  
        setLoading(false);  
      })  
      .catch((err) => {  
        setError(err.message);  
        setLoading(false);  
      });  
  }, []); // Empty dependency array: runs once on mount  

  if (loading) return <p>Loading users...</p>;  
  if (error) return <p>Error: {error}</p>;  

  return (  
    <div className="user-list">  
      <h2>Users from API</h2>  
      <ul>  
        {users.map((user) => (  
          <li key={user.id}>{user.name} ({user.email})</li>  
        ))}  
      </ul>  
    </div>  
  );  
}  

export default UserList;  
  • useEffect: Runs the fetch call after the component renders.
  • key: Required for lists in React to identify items uniquely.

Testing Your React App

CRA includes Jest (testing framework) and React Testing Library (for rendering components) out of the box.

Example: Testing the Counter Component

Open src/components/Counter.test.js and write a test:

import { render, screen, fireEvent } from '@testing-library/react';  
import Counter from './Counter';  

test('increments counter when button is clicked', () => {  
  render(<Counter />);  
  const counterElement = screen.getByText(/counter:/i);  
  const button = screen.getByText(/increment/i);  

  expect(counterElement).toContainElement(screen.getByText('0'));  

  fireEvent.click(button);  
  expect(counterElement).toContainElement(screen.getByText('1'));  
});  

Run tests with:

npm test  

Deploying Your React App

Once your app is ready, deploy it to share with the world!

Step 1: Build the Production Version

CRA generates an optimized build:

npm run build  

This creates a build/ folder with static HTML/CSS/JS files.

Step 2: Deploy to Vercel (Free)

  1. Push your code to GitHub.
  2. Sign up for Vercel and connect your GitHub repo.
  3. Vercel will auto-detect your React app and deploy it!

Conclusion

You’ve built a React frontend from scratch! You now understand:

  • Component creation and reusability with props.
  • State management with useState.
  • Event handling and form inputs.
  • Routing with React Router.
  • Data fetching with useEffect and APIs.
  • Styling and deployment.

React’s ecosystem is vast—next, explore state management libraries like Redux or Context API, or dive into advanced hooks like useReducer and useRef.

References