C
h
i
L
L
u
.
.
.

React.js Mastery Guide

Complete guide from basics to advanced patterns

Understanding React: The Modern UI Library

React is a declarative, component-based JavaScript library for building user interfaces. Created by Facebook in 2013, React revolutionized frontend development with its virtual DOM, component architecture, and unidirectional data flow. It powers millions of web applications from startups to enterprise-level systems.

What makes React unique is its component-based architecture that promotes reusability and maintainability. With the introduction of hooks in React 16.8, functional components became fully-featured, making React more intuitive and powerful than ever before.

Industry Standard: React is used by companies like Facebook, Instagram, Netflix, Airbnb, and Uber. Its vast ecosystem, strong community, and job market demand make it an essential skill for modern web developers.

1. React Basics & Components

Hello World: Your First React Component

React components are the building blocks of React applications. They can be written as functions or classes, with functional components being the modern standard.
// App.js - Main component
import React from 'react';

// Functional Component
function App() {
  return (
    <div className="app">
      <h1>Hello, React World!</h1>
      <p>Welcome to React programming</p>
      <WelcomeMessage name="Alice" />
    </div>
  );
}

// Component with props
function WelcomeMessage({ name }) {
  return (
    <div className="welcome">
      <h2>Welcome, {name}!</h2>
      <p>Today is {new Date().toLocaleDateString()}</p>
    </div>
  );
}

// Arrow function component
const Button = ({ onClick, children }) => {
  return (
    <button 
      className="btn btn-primary"
      onClick={onClick}
    >
      {children}
    </button>
  );
};

export default App;

// index.js - Entry point
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

JSX Syntax and Expressions

JSX is a syntax extension that allows writing HTML-like code in JavaScript. It makes React components more readable and expressive.
import React from 'react';

function JSXExamples() {
  const userName = "John Doe";
  const isLoggedIn = true;
  const userAge = 25;
  const fruits = ['Apple', 'Banana', 'Orange'];
  const user = {
    name: 'Alice',
    email: 'alice@example.com'
  };

  return (
    <div className="jsx-examples">
      {/* Variables in JSX */}
      <h1>Hello, {userName}!</h1>
      
      {/* Conditional rendering */}
      {isLoggedIn ? (
        <p>Welcome back!</p>
      ) : (
        <p>Please log in</p>
      )}
      
      {/* Short-circuit evaluation */}
      {isLoggedIn && <p>You are logged in</p>}
      
      {/* Array rendering */}
      <ul>
        {fruits.map((fruit, index) => (
          <li key={index}>{fruit}</li>
        ))}
      </ul>
      
      {/* Object properties */}
      <p>Name: {user.name}, Email: {user.email}</p>
      
      {/* Inline styles */}
      <div style={{
        padding: '20px',
        backgroundColor: '#f0f0f0',
        borderRadius: '8px'
      }}>
        Styled div
      </div>
      
      {/* CSS classes */}
      <div className={`box ${isLoggedIn ? 'active' : 'inactive'}`}>
        Dynamic classes
      </div>
      
      {/* Event handlers */}
      <button onClick={() => alert('Button clicked!')}>
        Click me
      </button>
    </div>
  );
}

export default JSXExamples;

Props: Passing Data Between Components

Props (properties) are how data flows from parent to child components in React. They are read-only and help make components reusable.
import React from 'react';

// Parent component
function UserDashboard() {
  const user = {
    name: 'Alice Johnson',
    role: 'Developer',
    joinDate: '2023-01-15',
    avatar: 'https://example.com/avatar.jpg'
  };

  const posts = [
    { id: 1, title: 'React Basics', likes: 42 },
    { id: 2, title: 'State Management', likes: 31 },
    { id: 3, title: 'Hooks Deep Dive', likes: 56 }
  ];

  return (
    <div className="dashboard">
      <UserProfile 
        user={user} 
        showAvatar={true}
        onUpdate={() => console.log('Profile updated')}
      />
      
      <PostList 
        posts={posts} 
        emptyMessage="No posts yet"
        renderItem={(post) => (
          <PostCard 
            key={post.id}
            title={post.title}
            likes={post.likes}
            onLike={() => console.log('Liked:', post.id)}
          />
        )}
      />
    </div>
  );
}

// Child component with props
function UserProfile({ user, showAvatar, onUpdate }) {
  return (
    <div className="user-profile">
      {showAvatar && (
        <img 
          src={user.avatar} 
          alt={user.name}
          className="avatar"
        />
      )}
      <div className="user-info">
        <h2>{user.name}</h2>
        <p>Role: {user.role}</p>
        <p>Joined: {new Date(user.joinDate).toLocaleDateString()}</p>
      </div>
      <button onClick={onUpdate}>
        Update Profile
      </button>
    </div>
  );
}

// Component with default props
function PostCard({ title, likes = 0, onLike }) {
  return (
    <div className="post-card">
      <h3>{title}</h3>
      <div className="post-actions">
        <span>{likes} likes</span>
        <button onClick={onLike}>Like</button>
      </div>
    </div>
  );
}

// Component with children prop
function Container({ children, className = '' }) {
  return (
    <div className={`container ${className}`}>
      {children}
    </div>
  );
}

// List component with render props
function PostList({ posts, emptyMessage, renderItem }) {
  if (posts.length === 0) {
    return <p>{emptyMessage}</p>;
  }

  return (
    <div className="post-list">
      {posts.map(renderItem)}
    </div>
  );
}

export default UserDashboard;

Component Composition and Reusability

React promotes composition over inheritance. By composing small, focused components, you can build complex UIs that are maintainable and reusable.
import React from 'react';

// Reusable Button component
function Button({ 
  variant = 'primary', 
  size = 'medium',
  disabled = false,
  onClick,
  children 
}) {
  const baseClasses = 'btn';
  const variantClass = `btn-${variant}`;
  const sizeClass = `btn-${size}`;
  const disabledClass = disabled ? 'btn-disabled' : '';

  return (
    <button
      className={`${baseClasses} ${variantClass} ${sizeClass} ${disabledClass}`}
      onClick={onClick}
      disabled={disabled}
    >
      {children}
    </button>
  );
}

// Card component
function Card({ header, footer, children }) {
  return (
    <div className="card">
      {header && <div className="card-header">{header}</div>}
      <div className="card-body">{children}</div>
      {footer && <div className="card-footer">{footer}</div>}
    </div>
  );
}

// Modal component
function Modal({ isOpen, onClose, title, children }) {
  if (!isOpen) return null;

  return (
    <div className="modal-overlay">
      <div className="modal">
        <div className="modal-header">
          <h3>{title}</h3>
          <button onClick={onClose} className="close-btn">Ɨ</button>
        </div>
        <div className="modal-content">
          {children}
        </div>
      </div>
    </div>
  );
}

// Using composition to build complex UI
function ProductPage() {
  const [showModal, setShowModal] = React.useState(false);

  return (
    <div className="product-page">
      <Card
        header={<h2>Amazing Product</h2>}
        footer={
          <div className="card-actions">
            <Button variant="primary" onClick={() => setShowModal(true)}>
              Buy Now
            </Button>
            <Button variant="outline">
              Add to Wishlist
            </Button>
          </div>
        }
      >
        <p>This is an amazing product description.</p>
        <ul>
          <li>Feature 1</li>
          <li>Feature 2</li>
          <li>Feature 3</li>
        </ul>
      </Card>

      <Modal
        isOpen={showModal}
        onClose={() => setShowModal(false)}
        title="Confirm Purchase"
      >
        <p>Are you sure you want to buy this product?</p>
        <div className="modal-actions">
          <Button variant="primary" onClick={() => {
            console.log('Purchase confirmed');
            setShowModal(false);
          }}>
            Confirm
          </Button>
          <Button variant="outline" onClick={() => setShowModal(false)}>
            Cancel
          </Button>
        </div>
      </Modal>
    </div>
  );
}

export default ProductPage;

2. React Hooks

useState: Managing Component State

The useState hook allows functional components to have state. It returns the current state and a function to update it.
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);

  const increment = () => setCount(count + step);
  const decrement = () => setCount(count - step);
  const reset = () => setCount(0);

  return (
    <div className="counter">
      <h2>Counter: {count}</h2>
      <div className="controls">
        <button onClick={decrement}>-</button>
        <button onClick={reset}>Reset</button>
        <button onClick={increment}>+</button>
      </div>
      <div className="step-control">
        <label>
          Step:
          <input
            type="number"
            value={step}
            onChange={(e) => setStep(Number(e.target.value))}
            min="1"
          />
        </label>
      </div>
    </div>
  );
}

function TodoList() {
  const [todos, setTodos] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const addTodo = () => {
    if (inputValue.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: inputValue,
        completed: false
      }]);
      setInputValue('');
    }
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div className="todo-list">
      <h2>Todo List ({todos.length})</h2>
      
      <div className="add-todo">
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
          placeholder="Add a new todo..."
        />
        <button onClick={addTodo}>Add</button>
      </div>

      <ul>
        {todos.map(todo => (
          <li key={todo.id} className={todo.completed ? 'completed' : ''}>
            <span onClick={() => toggleTodo(todo.id)}>
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

function FormWithMultipleStates() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    age: '',
    subscribe: false
  });

  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form submitted:', formData);
  };

  return (
    <form onSubmit={handleSubmit} className="user-form">
      <input
        name="name"
        value={formData.name}
        onChange={handleChange}
        placeholder="Name"
        required
      />
      <input
        name="email"
        type="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="Email"
        required
      />
      <input
        name="age"
        type="number"
        value={formData.age}
        onChange={handleChange}
        placeholder="Age"
      />
      <label>
        <input
          name="subscribe"
          type="checkbox"
          checked={formData.subscribe}
          onChange={handleChange}
        />
        Subscribe to newsletter
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}

export { Counter, TodoList, FormWithMultipleStates };

useEffect: Side Effects and Lifecycle

The useEffect hook lets you perform side effects in functional components. It combines the functionality of componentDidMount, componentDidUpdate, and componentWillUnmount.
import React, { useState, useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  // Effect with cleanup
  useEffect(() => {
    let mounted = true;
    
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();
        
        if (mounted) {
          setData(result);
          setError(null);
        }
      } catch (err) {
        if (mounted) {
          setError('Failed to fetch data');
          setData(null);
        }
      } finally {
        if (mounted) {
          setLoading(false);
        }
      }
    };

    fetchData();

    // Cleanup function
    return () => {
      mounted = false;
    };
  }, []); // Empty dependency array = run once on mount

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  
  return (
    <div>
      <h2>Fetched Data</h2>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

function Timer() {
  const [time, setTime] = useState(new Date());
  const [isRunning, setIsRunning] = useState(true);

  // Effect with dependency
  useEffect(() => {
    if (!isRunning) return;

    const interval = setInterval(() => {
      setTime(new Date());
    }, 1000);

    // Cleanup interval on unmount or when isRunning changes
    return () => clearInterval(interval);
  }, [isRunning]); // Re-run when isRunning changes

  return (
    <div className="timer">
      <h2>Current Time: {time.toLocaleTimeString()}</h2>
      <button onClick={() => setIsRunning(!isRunning)}>
        {isRunning ? 'Pause' : 'Resume'}
      </button>
    </div>
  );
}

function WindowSizeTracker() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight
  });

  // Effect for event listeners
  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    };

    window.addEventListener('resize', handleResize);
    
    // Cleanup event listener
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Empty array = setup and cleanup once

  return (
    <div>
      <p>Window size: {windowSize.width} x {windowSize.height}</p>
    </div>
  );
}

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  // Effect that depends on props
  useEffect(() => {
    if (!userId) return;

    const fetchUser = async () => {
      const response = await fetch(`/api/users/${userId}`);
      const userData = await response.json();
      setUser(userData);
    };

    fetchUser();
  }, [userId]); // Re-run when userId changes

  if (!user) return <div>Loading user...</div>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  );
}

export { DataFetcher, Timer, WindowSizeTracker, UserProfile };

Custom Hooks: Reusable Logic

Custom hooks let you extract component logic into reusable functions. They can use other hooks and help keep components clean and focused.
import { useState, useEffect, useCallback } from 'react';

// Custom hook for API calls
function useApi(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  const refetch = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, [url]);

  useEffect(() => {
    refetch();
  }, [refetch]);

  return { data, loading, error, refetch };
}

// Custom hook for local storage
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error('Error reading from localStorage:', error);
      return initialValue;
    }
  });

  const setValue = useCallback((value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error('Error saving to localStorage:', error);
    }
  }, [key, storedValue]);

  return [storedValue, setValue];
}

// Custom hook for toggle functionality
function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);

  const toggle = useCallback(() => setValue(prev => !prev), []);
  const setOn = useCallback(() => setValue(true), []);
  const setOff = useCallback(() => setValue(false), []);

  return [value, { toggle, setOn, setOff }];
}

// Custom hook for debounced values
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

// Using custom hooks in components
function UserSettings() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  const [isDarkMode, { toggle }] = useToggle(theme === 'dark');

  useEffect(() => {
    const newTheme = isDarkMode ? 'dark' : 'light';
    setTheme(newTheme);
    document.documentElement.setAttribute('data-theme', newTheme);
  }, [isDarkMode, setTheme]);

  return (
    <div className="user-settings">
      <h2>Settings</h2>
      <label>
        <input
          type="checkbox"
          checked={isDarkMode}
          onChange={toggle}
        />
        Dark Mode
      </label>
    </div>
  );
}

function SearchComponent() {
  const [query, setQuery] = useState('');
  const debouncedQuery = useDebounce(query, 500);
  const { data: results, loading } = useApi(
    debouncedQuery ? `/api/search?q=${debouncedQuery}` : ''
  );

  return (
    <div className="search">
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      {loading && <div>Searching...</div>}
      {results && (
        <ul>
          {results.map(item => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export { 
  useApi, 
  useLocalStorage, 
  useToggle, 
  useDebounce,
  UserSettings,
  SearchComponent
};

3. State Management

useReducer: Complex State Logic

useReducer is preferable to useState when you have complex state logic involving multiple sub-values or when the next state depends on the previous one.
import React, { useReducer } from 'react';

// Reducer function
function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        ...state,
        todos: [...state.todos, {
          id: Date.now(),
          text: action.text,
          completed: false
        }]
      };
    
    case 'TOGGLE_TODO':
      return {
        ...state,
        todos: state.todos.map(todo =>
          todo.id === action.id 
            ? { ...todo, completed: !todo.completed }
            : todo
        )
      };
    
    case 'DELETE_TODO':
      return {
        ...state,
        todos: state.todos.filter(todo => todo.id !== action.id)
      };
    
    case 'SET_FILTER':
      return {
        ...state,
        filter: action.filter
      };
    
    case 'CLEAR_COMPLETED':
      return {
        ...state,
        todos: state.todos.filter(todo => !todo.completed)
      };
    
    default:
      return state;
  }
}

const initialState = {
  todos: [],
  filter: 'all' // all, active, completed
};

function TodoApp() {
  const [state, dispatch] = useReducer(todoReducer, initialState);

  const { todos, filter } = state;

  const addTodo = (text) => {
    if (text.trim()) {
      dispatch({ type: 'ADD_TODO', text });
    }
  };

  const filteredTodos = todos.filter(todo => {
    switch (filter) {
      case 'active': return !todo.completed;
      case 'completed': return todo.completed;
      default: return true;
    }
  });

  return (
    <div className="todo-app">
      <h1>Todo App (useReducer)</h1>
      
      <TodoInput onAdd={addTodo} />
      
      <div className="filters">
        {['all', 'active', 'completed'].map(filterType => (
          <button
            key={filterType}
            onClick={() => dispatch({ type: 'SET_FILTER', filter: filterType })}
            className={filter === filterType ? 'active' : ''}
          >
            {filterType}
          </button>
        ))}
      </div>

      <TodoList
        todos={filteredTodos}
        onToggle={id => dispatch({ type: 'TOGGLE_TODO', id })}
        onDelete={id => dispatch({ type: 'DELETE_TODO', id })}
      />

      <button 
        onClick={() => dispatch({ type: 'CLEAR_COMPLETED' })}
        className="clear-btn"
      >
        Clear Completed
      </button>
    </div>
  );
}

function TodoInput({ onAdd }) {
  const [text, setText] = React.useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    onAdd(text);
    setText('');
  };

  return (
    <form onSubmit={handleSubmit} className="todo-input">
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add a new todo..."
      />
      <button type="submit">Add</button>
    </form>
  );
}

function TodoList({ todos, onToggle, onDelete }) {
  return (
    <ul className="todo-list">
      {todos.map(todo => (
        <li key={todo.id} className={todo.completed ? 'completed' : ''}>
          <span onClick={() => onToggle(todo.id)}>
            {todo.text}
          </span>
          <button onClick={() => onDelete(todo.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

// Shopping Cart Example with useReducer
function cartReducer(state, action) {
  switch (action.type) {
    case 'ADD_ITEM':
      const existingItem = state.items.find(item => item.id === action.item.id);
      if (existingItem) {
        return {
          ...state,
          items: state.items.map(item =>
            item.id === action.item.id
              ? { ...item, quantity: item.quantity + 1 }
              : item
          )
        };
      }
      return {
        ...state,
        items: [...state.items, { ...action.item, quantity: 1 }]
      };
    
    case 'REMOVE_ITEM':
      return {
        ...state,
        items: state.items.filter(item => item.id !== action.id)
      };
    
    case 'UPDATE_QUANTITY':
      return {
        ...state,
        items: state.items.map(item =>
          item.id === action.id
            ? { ...item, quantity: action.quantity }
            : item
        )
      };
    
    case 'CLEAR_CART':
      return {
        ...state,
        items: []
      };
    
    default:
      return state;
  }
}

function ShoppingCart() {
  const [state, dispatch] = useReducer(cartReducer, { items: [] });

  const total = state.items.reduce(
    (sum, item) => sum + item.price * item.quantity, 0
  );

  return (
    <div className="shopping-cart">
      <h2>Shopping Cart</h2>
      {state.items.length === 0 ? (
        <p>Your cart is empty</p>
      ) : (
        <>
          {state.items.map(item => (
            <div key={item.id} className="cart-item">
              <span>{item.name}</span>
              <input
                type="number"
                value={item.quantity}
                onChange={(e) => dispatch({
                  type: 'UPDATE_QUANTITY',
                  id: item.id,
                  quantity: parseInt(e.target.value)
                })}
                min="1"
              />
              <span>${(item.price * item.quantity).toFixed(2)}</span>
              <button onClick={() => dispatch({ type: 'REMOVE_ITEM', id: item.id })}>
                Remove
              </button>
            </div>
          ))}
          <div className="cart-total">
            Total: ${total.toFixed(2)}
          </div>
          <button onClick={() => dispatch({ type: 'CLEAR_CART' })}>
            Clear Cart
          </button>
        </>
      )}
    </div>
  );
}

export { TodoApp, ShoppingCart };

Context API: Global State Management

The Context API provides a way to pass data through the component tree without having to pass props down manually at every level.
import React, { createContext, useContext, useReducer } from 'react';

// Create Context
const AuthContext = createContext();

// Auth reducer
function authReducer(state, action) {
  switch (action.type) {
    case 'LOGIN':
      return {
        ...state,
        user: action.user,
        isAuthenticated: true
      };
    
    case 'LOGOUT':
      return {
        ...state,
        user: null,
        isAuthenticated: false
      };
    
    case 'UPDATE_USER':
      return {
        ...state,
        user: { ...state.user, ...action.updates }
      };
    
    default:
      return state;
  }
}

const initialState = {
  user: null,
  isAuthenticated: false
};

// Context Provider
function AuthProvider({ children }) {
  const [state, dispatch] = useReducer(authReducer, initialState);

  const login = (user) => dispatch({ type: 'LOGIN', user });
  const logout = () => dispatch({ type: 'LOGOUT' });
  const updateUser = (updates) => dispatch({ type: 'UPDATE_USER', updates });

  const value = {
    ...state,
    login,
    logout,
    updateUser
  };

  return (
    <AuthContext.Provider value={value}>
      {children}
    </AuthContext.Provider>
  );
}

// Custom hook to use auth context
function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

// Components using the context
function LoginForm() {
  const { login } = useAuth();
  const [credentials, setCredentials] = React.useState({
    email: '',
    password: ''
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    // Simulate login
    login({
      id: 1,
      name: 'John Doe',
      email: credentials.email
    });
  };

  return (
    <form onSubmit={handleSubmit} className="login-form">
      <input
        type="email"
        value={credentials.email}
        onChange={(e) => setCredentials(prev => ({
          ...prev,
          email: e.target.value
        }))}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={credentials.password}
        onChange={(e) => setCredentials(prev => ({
          ...prev,
          password: e.target.value
        }))}
        placeholder="Password"
        required
      />
      <button type="submit">Login</button>
    </form>
  );
}

function UserProfile() {
  const { user, updateUser } = useAuth();

  if (!user) return null;

  return (
    <div className="user-profile">
      <h2>Welcome, {user.name}!</h2>
      <p>Email: {user.email}</p>
      <button onClick={() => updateUser({ name: 'Jane Doe' })}>
        Update Name
      </button>
    </div>
  );
}

function Header() {
  const { user, isAuthenticated, logout } = useAuth();

  return (
    <header className="app-header">
      <h1>My App</h1>
      <div className="user-info">
        {isAuthenticated ? (
          <>
            <span>Hello, {user?.name}</span>
            <button onClick={logout}>Logout</button>
          </>
        ) : (
          <span>Please log in</span>
        )}
      </div>
    </header>
  );
}

// Main App component
function App() {
  return (
    <AuthProvider>
      <div className="app">
        <Header />
        <main>
          <AuthWrapper />
        </main>
      </div>
    </AuthProvider>
  );
}

function AuthWrapper() {
  const { isAuthenticated } = useAuth();

  return (
    <div className="auth-wrapper">
      {isAuthenticated ? <UserProfile /> : <LoginForm />}
    </div>
  );
}

// Theme Context Example
const ThemeContext = createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = React.useState('light');

  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <div data-theme={theme}>
        {children}
      </div>
    </ThemeContext.Provider>
  );
}

function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
}

function ThemeToggle() {
  const { theme, toggleTheme } = useTheme();

  return (
    <button onClick={toggleTheme} className="theme-toggle">
      Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
    </button>
  );
}

export { 
  App, 
  ThemeProvider, 
  ThemeToggle,
  useAuth,
  useTheme 
};

šŸ’» React Practice Projects

Beginner Level

  • 1Build a Todo List App with useState and useEffect
  • 2Create a Weather App with API integration
  • 3Implement a Calculator with component composition
  • 4Build a Markdown Previewer with real-time updates
  • 5Create a Shopping Cart with state management

Intermediate Level

  • 1Develop a Blog Platform with React Router
  • 2Build a Real-time Chat App with WebSockets
  • 3Create a Dashboard with charts and data visualization
  • 4Implement a Drag-and-drop Task Board
  • 5Build a Social Media Feed with infinite scrolling

Advanced Level

  • 1Create a Micro-frontend Architecture
  • 2Build a Design System with Storybook
  • 3Implement Server-side Rendering with Next.js
  • 4Develop a Progressive Web App (PWA)
  • 5Build a Real-time Collaborative Editor

šŸ“‹ React Quick Reference

Essential Hooks

  • •useState - Component state
  • •useEffect - Side effects
  • •useContext - Global state
  • •useReducer - Complex state
  • •useCallback - Memoized functions
  • •useMemo - Memoized values
  • •useRef - DOM references

Common Patterns

  • •Component Composition
  • •Render Props
  • •Higher-Order Components
  • •Custom Hooks
  • •Context API
  • •Error Boundaries
  • •Code Splitting

Master Modern Web Development!

React has revolutionized how we build user interfaces, making it possible to create highly interactive and performant web applications. Its component-based architecture and rich ecosystem make it the most popular frontend library in the world.

With modern React features like hooks, context, and concurrent features, you can build applications that are more maintainable, testable, and scalable than ever before.

Happy React Coding! āš›ļø

This comprehensive guide covers React from basic components to advanced patterns like hooks, state management, and context API.

Essential for modern frontend development and building scalable web applications.

Ā© 2025 React.js Mastery Guide | Modern Web Development