⚛️ React — Zero to Hero
Build modern UIs with the world's most popular JavaScript library
⚛️ What is React?
React is a JavaScript library by Meta for building user interfaces. It uses a component-based architecture and a virtual DOM for fast, efficient updates.
🧩 Components
Break UI into reusable, independent pieces.
🔄 Reactive State
UI re-renders automatically when data changes.
⚡ Virtual DOM
React diffs changes and updates only what's needed.
🌍 Huge Ecosystem
Used by Meta, Netflix, Airbnb, Twitter.
⚙️ Setup
# Create a new React app (Vite — recommended) npm create vite@latest my-app -- --template react cd my-app npm install npm run dev # Or with Create React App npx create-react-app my-app cd my-app npm start
🔷 JSX
JSX is HTML-like syntax inside JavaScript. It compiles to React.createElement() calls.
// JSX rules: const el = ( <div className="card"> // class → className <h1>Hello {name}</h1> // JS in {} <img src="/logo.png" /> // self-closing {isLoggedIn && <p>Welcome!</p>} // conditional </div> );
🧩 Components
// Function component (modern standard) function Button({ label, onClick }) { return ( <button onClick={onClick} className="btn"> {label} </button> ); } // Use it function App() { return <Button label="Click me" onClick={() => alert('Hi!')} />; }
📨 Props
Props are read-only inputs passed from parent to child — like HTML attributes.
function Card({ title, description, image }) { return ( <div className="card"> <img src={image} alt={title} /> <h2>{title}</h2> <p>{description}</p> </div> ); } // Default props Card.defaultProps = { image: '/placeholder.png' };
🔄 useState
useState stores data that changes over time and triggers a re-render.
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>+</button> <button onClick={() => setCount(0)}>Reset</button> </div> ); }
setCount(count + 1), never count++.💫 useEffect
Run side effects: fetch data, subscribe to events, update the DOM.
import { useState, useEffect } from 'react'; function Users() { const [users, setUsers] = useState([]); useEffect(() => { // Runs after render fetch('https://jsonplaceholder.typicode.com/users') .then(r => r.json()) .then(data => setUsers(data)); return () => { /* cleanup */ }; }, []); // [] = run once on mount return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>; }
🖱 Events
function Form() { const handleClick = (e) => console.log('clicked', e); const handleChange = (e) => console.log(e.target.value); const handleSubmit = (e) => { e.preventDefault(); /* ... */ }; return ( <form onSubmit={handleSubmit}> <input onChange={handleChange} /> <button onClick={handleClick}>Submit</button> </form> ); }
📋 Rendering Lists
const fruits = ['Apple', 'Banana', 'Cherry']; function FruitList() { return ( <ul> {fruits.map((fruit, index) => ( <li key={index}>{fruit}</li> ))} </ul> ); }
key prop when rendering lists. Use IDs from your data, not array indexes, when possible.📝 Controlled Forms
function LoginForm() { const [email, setEmail] = useState(''); const [pass, setPass] = useState(''); const handleSubmit = (e) => { e.preventDefault(); console.log({ email, pass }); }; return ( <form onSubmit={handleSubmit}> <input value={email} onChange={e => setEmail(e.target.value)} type="email" /> <input value={pass} onChange={e => setPass(e.target.value)} type="password" /> <button>Login</button> </form> ); }
🌐 Context API
Share state globally without prop-drilling through every component.
import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); function ThemeProvider({ children }) { const [dark, setDark] = useState(false); return ( <ThemeContext.Provider value={{ dark, setDark }}> {children} </ThemeContext.Provider> ); } // Consume anywhere function Navbar() { const { dark, setDark } = useContext(ThemeContext); return <button onClick={() => setDark(!dark)}>{dark ? '☀️' : '🌙'}</button>; }
🪝 Custom Hooks
// useFetch — reusable data fetching hook function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(url) .then(r => r.json()) .then(setData) .catch(setError) .finally(() => setLoading(false)); }, [url]); return { data, loading, error }; } // Usage const { data, loading } = useFetch('/api/users');
🔗 React Router
# Install
npm install react-router-dom
import { BrowserRouter, Routes, Route, Link, useParams } from 'react-router-dom'; function App() { return ( <BrowserRouter> <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/post/:id" element={<Post />} /> </Routes> </BrowserRouter> ); } function Post() { const { id } = useParams(); return <h1>Post #{id}</h1>; }
🚀 Pro Tips
// 1. useMemo — cache expensive calculations const total = useMemo(() => items.reduce((s,i) => s+i.price, 0), [items]); // 2. useCallback — stable function reference const handleClick = useCallback(() => doSomething(id), [id]); // 3. Lazy loading const Dashboard = React.lazy(() => import('./Dashboard')); // 4. Optional chaining in JSX <p>{user?.profile?.bio ?? 'No bio'}</p> // 5. Spread props <Input {...register('email')} type="email" />