Om Pandey
React.js

React.js

A JavaScript Library for Building User Interfaces

Master React - the most popular frontend library. Build fast, interactive, and scalable user interfaces with component-based architecture. From beginner to pro!

Component Based Virtual DOM Reactive Updates Reusable Code

What You'll Learn

1

Introduction to React

React is a JavaScript library for building user interfaces, developed by Facebook. It allows you to create reusable UI components and efficiently update the DOM through its Virtual DOM mechanism.

Why React?

Component-Based: Build encapsulated components that manage their own state. Used by Facebook, Instagram, Netflix, Airbnb, and many more!

React Component Architecture
App Component
Child Components
Props & State
Virtual DOM
Real DOM
Key Concepts:
  • Components: Reusable building blocks of your UI
  • JSX: JavaScript XML - write HTML-like syntax in JavaScript
  • Virtual DOM: Efficient DOM updates through diffing algorithm
  • One-Way Data Flow: Data flows from parent to child via props
2

Setup & Installation

1

Install Node.js

Make sure you have Node.js 18+ installed. Check with node --version

2

Create React App (Vite - Recommended)

Vite is the modern, faster alternative to Create React App

Terminal
$ # Create React app with Vite $ npm create vite@latest my-react-app -- --template react $ # Navigate to project $ cd my-react-app $ # Install dependencies $ npm install $ # Start development server $ npm run dev VITE v5.0.0 ready in 300 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose

Open http://localhost:5173/ in your browser - You'll see the React welcome page!

📁 my-react-app/ ├── 📁 node_modules/ ├── 📁 public/ │ └── vite.svg ├── 📁 src/ │ ├── 📁 assets/ │ ├── App.jsx # Main App component │ ├── App.css # App styles │ ├── main.jsx # Entry point │ └── index.css # Global styles ├── index.html ├── package.json └── vite.config.js

React App Created!

Your React development environment is ready!

3

JSX Syntax

JSX (JavaScript XML) is a syntax extension that lets you write HTML-like code in JavaScript. It's not required for React, but it makes the code more readable and easier to write.

Basic JSX

App.jsx
JSX
// JSX looks like HTML but it's JavaScript!
function App() {
  const name = "Om Pandey";
  const age = 25;
  
  return (
    <div className="container">
      {/* This is a JSX comment */}
      <h1>Hello, {name}!</h1>
      <p>You are {age} years old.</p>
      <p>2 + 2 = {2 + 2}</p>
    </div>
  );
}

export default App;
Browser Output
Hello, Om Pandey! You are 25 years old. 2 + 2 = 4

JSX Rules

JSX Rules
JSX
// Rule 1: Return single root element
// ❌ Wrong
return (
  <h1>Title</h1>
  <p>Paragraph</p>
);

// ✅ Correct - wrap in a parent or use Fragment
return (
  <>
    <h1>Title</h1>
    <p>Paragraph</p>
  </>
);

// Rule 2: Use className instead of class
<div className="my-class">Content</div>

// Rule 3: Use camelCase for attributes
<button onClick={handleClick}>Click</button>
<label htmlFor="name">Name</label>
<input tabIndex={1} />

// Rule 4: Close all tags
<img src="photo.jpg" alt="Photo" />
<br />
<input type="text" />

// Rule 5: Use curly braces for JavaScript
<p style={{ color: 'red', fontSize: '20px' }}>Styled</p>

Important!

JSX is transpiled to JavaScript by Babel. <div> becomes React.createElement('div')

4

Components

Components are the building blocks of React applications. They are reusable, independent pieces of UI that can have their own logic and styling.

Function Components

components/Header.jsx
// Function Component (Recommended)
function Header() {
  return (
    <header>
      <h1>My Website</h1>
      <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
      </nav>
    </header>
  );
}

export default Header;
components/Card.jsx
// Arrow Function Component
const Card = () => {
  return (
    <div className="card">
      <h2>Card Title</h2>
      <p>Card content goes here...</p>
    </div>
  );
};

export default Card;

Using Components

App.jsx
import Header from './components/Header';
import Card from './components/Card';
import Footer from './components/Footer';

function App() {
  return (
    <div className="app">
      <Header />
      
      <main>
        <Card />
        <Card />
        <Card />
      </main>
      
      <Footer />
    </div>
  );
}

export default App;

Component Naming

Components must start with an uppercase letter. <Header /> is a component, <header> is HTML.

5

Props & Data Flow

Props (properties) are how you pass data from a parent component to a child component. They are read-only and help make components reusable.

Passing Props

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

function App() {
  return (
    <div>
      {/* Passing props to child component */}
      <UserCard 
        name="Om Pandey"
        age={25}
        isAdmin={true}
        skills={['React', 'JavaScript', 'Python']}
      />
      
      <UserCard 
        name="John Doe"
        age={30}
        isAdmin={false}
        skills={['HTML', 'CSS']}
      />
    </div>
  );
}

Receiving Props

components/UserCard.jsx
// Method 1: Props object
function UserCard(props) {
  return (
    <div className="user-card">
      <h2>{props.name}</h2>
      <p>Age: {props.age}</p>
      <p>Role: {props.isAdmin ? 'Admin' : 'User'}</p>
    </div>
  );
}

// Method 2: Destructuring (Recommended)
function UserCard({ name, age, isAdmin, skills }) {
  return (
    <div className="user-card">
      <h2>{name}</h2>
      <p>Age: {age}</p>
      <p>Role: {isAdmin ? 'Admin' : 'User'}</p>
      <ul>
        {skills.map((skill, index) => (
          <li key={index}>{skill}</li>
        ))}
      </ul>
    </div>
  );
}

export default UserCard;

Default Props

components/Button.jsx
// Default values using destructuring
function Button({ 
  text = "Click Me", 
  color = "blue", 
  size = "medium",
  onClick 
}) {
  return (
    <button 
      className={`btn btn-${color} btn-${size}`}
      onClick={onClick}
    >
      {text}
    </button>
  );
}

export default Button;

// Usage:
// <Button />  - Uses all defaults
// <Button text="Submit" color="green" />

Children Props

components/Card.jsx
// Card component that accepts children
function Card({ title, children }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div className="card-body">
        {children}
      </div>
    </div>
  );
}

// Usage in App.jsx
function App() {
  return (
    <Card title="Welcome">
      <p>This is the card content.</p>
      <button>Learn More</button>
    </Card>
  );
}
6

State Management

State is data that changes over time in your component. When state changes, React re-renders the component to reflect the new data.

useState Hook

Counter.jsx
import { useState } from 'react';

function Counter() {
  // Declare state: [value, setterFunction] = useState(initialValue)
  const [count, setCount] = useState(0);
  
  const increment = () => {
    setCount(count + 1);
  };
  
  const decrement = () => {
    setCount(count - 1);
  };
  
  const reset = () => {
    setCount(0);
  };
  
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={decrement}>-</button>
      <button onClick={increment}>+</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

export default Counter;

State with Different Types

StateExamples.jsx
import { useState } from 'react';

function StateExamples() {
  // String state
  const [name, setName] = useState('');
  
  // Boolean state
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  
  // Array state
  const [items, setItems] = useState(['Apple', 'Banana']);
  
  // Object state
  const [user, setUser] = useState({
    name: 'Om',
    email: '[email protected]'
  });
  
  // Update array - add item
  const addItem = () => {
    setItems([...items, 'Orange']);
  };
  
  // Update array - remove item
  const removeItem = (index) => {
    setItems(items.filter((_, i) => i !== index));
  };
  
  // Update object - partial update
  const updateEmail = () => {
    setUser({ ...user, email: '[email protected]' });
  };
  
  return (
    <div>
      <input 
        value={name} 
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter name"
      />
      <p>Hello, {name || 'Guest'}!</p>
      
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        {isLoggedIn ? 'Logout' : 'Login'}
      </button>
      
      <ul>
        {items.map((item, i) => <li key={i}>{item}</li>)}
      </ul>
      <button onClick={addItem}>Add Item</button>
    </div>
  );
}

Never Mutate State Directly!

Always create a new copy of arrays/objects when updating. Use spread operator: [...array] or {...object}

7

React Hooks

Hooks are functions that let you use state and other React features in function components.

Hook Purpose Example
useState Manage component state const [count, setCount] = useState(0)
useEffect Side effects (API calls, subscriptions) useEffect(() => { ... }, [deps])
useContext Access context values const theme = useContext(ThemeContext)
useRef Reference DOM elements or persist values const inputRef = useRef(null)
useMemo Memoize expensive calculations const value = useMemo(() => compute(), [deps])
useCallback Memoize functions const fn = useCallback(() => {}, [deps])

useRef Hook

FocusInput.jsx
import { useRef } from 'react';

function FocusInput() {
  const inputRef = useRef(null);
  
  const focusInput = () => {
    inputRef.current.focus();
  };
  
  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

Rules of Hooks

1. Only call hooks at the top level (not inside loops, conditions, or nested functions)
2. Only call hooks from React function components or custom hooks

8

Event Handling

React events are named using camelCase and you pass a function as the event handler.

EventExamples.jsx
import { useState } from 'react';

function EventExamples() {
  const [message, setMessage] = useState('');
  
  // Click event
  const handleClick = () => {
    alert('Button clicked!');
  };
  
  // Click with parameter
  const handleGreet = (name) => {
    alert(`Hello, ${name}!`);
  };
  
  // Event object
  const handleInputChange = (event) => {
    setMessage(event.target.value);
  };
  
  // Prevent default behavior
  const handleSubmit = (event) => {
    event.preventDefault();
    console.log('Form submitted!');
  };
  
  return (
    <div>
      {/* Basic click */}
      <button onClick={handleClick}>Click Me</button>
      
      {/* Click with parameter - use arrow function */}
      <button onClick={() => handleGreet('Om')}>Greet</button>
      
      {/* Input change */}
      <input 
        type="text"
        value={message}
        onChange={handleInputChange}
        onFocus={() => console.log('Focused!')}
        onBlur={() => console.log('Blurred!')}
      />
      
      {/* Form submit */}
      <form onSubmit={handleSubmit}>
        <button type="submit">Submit</button>
      </form>
      
      {/* Mouse events */}
      <div
        onMouseEnter={() => console.log('Mouse entered')}
        onMouseLeave={() => console.log('Mouse left')}
      >
        Hover over me
      </div>
    </div>
  );
}
9

Conditional Rendering

ConditionalRendering.jsx
import { useState } from 'react';

function ConditionalRendering() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  
  return (
    <div>
      {/* Method 1: If-Else with ternary */}
      {isLoggedIn ? (
        <h1>Welcome back!</h1>
      ) : (
        <h1>Please log in</h1>
      )}
      
      {/* Method 2: Logical AND (&&) - render if true */}
      {isLoggedIn && <button>Logout</button>}
      
      {/* Method 3: Logical OR (||) - render if false/empty */}
      {items.length || <p>No items found</p>}
      
      {/* Method 4: Nullish coalescing */}
      <p>{name ?? 'Anonymous'}</p>
      
      {/* Method 5: Multiple conditions */}
      {loading ? (
        <p>Loading...</p>
      ) : items.length > 0 ? (
        <ul>
          {items.map(item => <li key={item.id}>{item.name}</li>)}
        </ul>
      ) : (
        <p>No items available</p>
      )}
      
      <button onClick={() => setIsLoggedIn(!isLoggedIn)}>
        Toggle Login
      </button>
    </div>
  );
}
10

Lists & Keys

TodoList.jsx
import { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: 'Learn React', completed: false },
    { id: 2, text: 'Build Projects', completed: false },
    { id: 3, text: 'Get a Job', completed: false },
  ]);
  
  const [newTodo, setNewTodo] = useState('');
  
  // Add new todo
  const addTodo = () => {
    if (newTodo.trim()) {
      setTodos([
        ...todos,
        { id: Date.now(), text: newTodo, completed: false }
      ]);
      setNewTodo('');
    }
  };
  
  // Toggle complete
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
  
  // Delete todo
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  return (
    <div>
      <h1>Todo List</h1>
      
      <div>
        <input
          value={newTodo}
          onChange={(e) => setNewTodo(e.target.value)}
          placeholder="Add new todo"
        />
        <button onClick={addTodo}>Add</button>
      </div>
      
      <ul>
        {todos.map(todo => (
          {/* Always use unique key! */}
          <li key={todo.id}>
            <span
              style={{ 
                textDecoration: todo.completed ? 'line-through' : 'none' 
              }}
              onClick={() => toggleTodo(todo.id)}
            >
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
      
      <p>Total: {todos.length} | Completed: {todos.filter(t => t.completed).length}</p>
    </div>
  );
}

Keys are Important!

Always use unique, stable keys when rendering lists. Don't use array index if the list can change. Use id from your data.

11

Forms & Input

ContactForm.jsx
import { useState } from 'react';

function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
    subscribe: false,
    country: 'nepal'
  });
  
  const [errors, setErrors] = useState({});
  
  // Handle all input changes
  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData({
      ...formData,
      [name]: type === 'checkbox' ? checked : value
    });
  };
  
  // Validate form
  const validate = () => {
    const newErrors = {};
    if (!formData.name) newErrors.name = 'Name is required';
    if (!formData.email.includes('@')) newErrors.email = 'Invalid email';
    if (formData.message.length < 10) newErrors.message = 'Message too short';
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  // Handle submit
  const handleSubmit = (e) => {
    e.preventDefault();
    if (validate()) {
      console.log('Form submitted:', formData);
      // Reset form
      setFormData({ name: '', email: '', message: '', subscribe: false, country: 'nepal' });
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Name:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
        />
        {errors.name && <span className="error">{errors.name}</span>}
      </div>
      
      <div>
        <label>Email:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>
      
      <div>
        <label>Country:</label>
        <select name="country" value={formData.country} onChange={handleChange}>
          <option value="nepal">Nepal</option>
          <option value="india">India</option>
          <option value="usa">USA</option>
        </select>
      </div>
      
      <div>
        <label>Message:</label>
        <textarea
          name="message"
          value={formData.message}
          onChange={handleChange}
        />
      </div>
      
      <div>
        <label>
          <input
            type="checkbox"
            name="subscribe"
            checked={formData.subscribe}
            onChange={handleChange}
          />
          Subscribe to newsletter
        </label>
      </div>
      
      <button type="submit">Submit</button>
    </form>
  );
}
12

useEffect & Side Effects

useEffect lets you perform side effects in function components - data fetching, subscriptions, manually changing the DOM, etc.

DataFetching.jsx
import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  // Fetch data on component mount
  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/users');
        if (!response.ok) throw new Error('Failed to fetch');
        const data = await response.json();
        setUsers(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchUsers();
  }, []); // Empty array = run once on mount
  
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;
  
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name} - {user.email}</li>
      ))}
    </ul>
  );
}
useEffect Patterns
JSX
// Pattern 1: Run on every render (no dependency array)
useEffect(() => {
  console.log('Runs on every render');
});

// Pattern 2: Run once on mount (empty array)
useEffect(() => {
  console.log('Runs only once on mount');
}, []);

// Pattern 3: Run when dependency changes
useEffect(() => {
  console.log(`Count changed to: ${count}`);
}, [count]);

// Pattern 4: Cleanup function (return)
useEffect(() => {
  const timer = setInterval(() => {
    console.log('Tick');
  }, 1000);
  
  // Cleanup when component unmounts or before re-run
  return () => {
    clearInterval(timer);
    console.log('Cleaned up!');
  };
}, []);
13

Context API

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

context/ThemeContext.jsx
import { createContext, useState, useContext } from 'react';

// 1. Create Context
const ThemeContext = createContext();

// 2. Create Provider Component
export function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// 3. Custom Hook for easy access
export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return context;
}
App.jsx & Component.jsx
// App.jsx - Wrap with Provider
import { ThemeProvider } from './context/ThemeContext';

function App() {
  return (
    <ThemeProvider>
      <Navbar />
      <MainContent />
    </ThemeProvider>
  );
}

// Navbar.jsx - Use context
import { useTheme } from './context/ThemeContext';

function Navbar() {
  const { theme, toggleTheme } = useTheme();
  
  return (
    <nav className={`navbar ${theme}`}>
      <h1>My App</h1>
      <button onClick={toggleTheme}>
        Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
      </button>
    </nav>
  );
}
14

React Router

Terminal
$ npm install react-router-dom
App.jsx
import { BrowserRouter, Routes, Route, Link, useParams, useNavigate } from 'react-router-dom';

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

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

function UserProfile() {
  const { userId } = useParams();
  const navigate = useNavigate();
  
  return (
    <div>
      <h1>User Profile: {userId}</h1>
      <button onClick={() => navigate('/')}>Go Home</button>
      <button onClick={() => navigate(-1)}>Go Back</button>
    </div>
  );
}

function NotFound() {
  return <h1>404 - Page Not Found</h1>;
}

// Navigation
function Navbar() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
      <Link to="/user/123">Profile</Link>
    </nav>
  );
}

// App with Router
function App() {
  return (
    <BrowserRouter>
      <Navbar />
      
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/user/:userId" element={<UserProfile />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;
15

Advanced Patterns

Custom Hooks

hooks/useFetch.js
import { useState, useEffect } from 'react';

// Custom hook for data fetching
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await fetch(url);
        if (!response.ok) throw new Error('Failed to fetch');
        const json = await response.json();
        setData(json);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchData();
  }, [url]);
  
  return { data, loading, error };
}

export default useFetch;

// Usage
function UserList() {
  const { data: users, loading, error } = useFetch('https://api.example.com/users');
  
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;
  
  return <ul>{users?.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

useLocalStorage Hook

hooks/useLocalStorage.js
import { useState } from 'react';

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });
  
  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };
  
  return [storedValue, setValue];
}

export default useLocalStorage;

// Usage
function Settings() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  const [user, setUser] = useLocalStorage('user', { name: '' });
  
  return (
    <div>
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        Current: {theme}
      </button>
    </div>
  );
}

Performance Optimization

Optimization.jsx
import { useState, useMemo, useCallback, memo } from 'react';

// useMemo - Memoize expensive calculations
function ExpensiveList({ items, filter }) {
  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter(item => item.includes(filter));
  }, [items, filter]); // Only recalculate when items or filter changes
  
  return (
    <ul>
      {filteredItems.map((item, i) => <li key={i}>{item}</li>)}
    </ul>
  );
}

// useCallback - Memoize functions
function Parent() {
  const [count, setCount] = useState(0);
  
  // Without useCallback, this creates new function on every render
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []); // Empty deps = function never changes
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <MemoizedChild onClick={handleClick} />
    </div>
  );
}

// React.memo - Prevent unnecessary re-renders
const MemoizedChild = memo(function Child({ onClick }) {
  console.log('Child rendered');
  return <button onClick={onClick}>Click me</button>;
});

// Lazy Loading Components
import { lazy, Suspense } from 'react';

const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

Error Boundaries

ErrorBoundary.jsx
import { Component } from 'react';

// Error Boundaries must be class components
class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
  
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  
  componentDidCatch(error, errorInfo) {
    console.error('Error caught:', error, errorInfo);
    // Log to error reporting service
  }
  
  render() {
    if (this.state.hasError) {
      return (
        <div className="error-fallback">
          <h2>Something went wrong!</h2>
          <button onClick={() => this.setState({ hasError: false })}>
            Try Again
          </button>
        </div>
      );
    }
    
    return this.props.children;
  }
}

export default ErrorBoundary;

// Usage in App.jsx
function App() {
  return (
    <ErrorBoundary>
      <MyComponent />
    </ErrorBoundary>
  );
}

Recommended Project Structure

📁 src/ ├── 📁 assets/ # Images, fonts, etc. ├── 📁 components/ # Reusable components │ ├── 📁 common/ # Button, Input, Modal │ ├── 📁 layout/ # Header, Footer, Sidebar │ └── 📁 ui/ # Card, Badge, Avatar ├── 📁 context/ # React Context files ├── 📁 hooks/ # Custom hooks ├── 📁 pages/ # Page components │ ├── Home.jsx │ ├── About.jsx │ └── Contact.jsx ├── 📁 services/ # API calls │ └── api.js ├── 📁 utils/ # Utility functions ├── 📁 styles/ # Global CSS/SCSS ├── App.jsx ├── main.jsx └── index.css

You're Ready!

You now have all the knowledge to build modern React applications. Practice by building projects!

Congratulations!

You've mastered React.js from zero to hero! You're now ready to build amazing user interfaces. Keep practicing and building projects!