Learn React
in 10 Days
A structured, hands-on journey from zero to building real React apps. Every topic explained with examples, use-cases, and daily tasks.
Setup, JSX & The React Mental Model
Getting your environment ready and understanding how React thinks
React is a JavaScript library built by Meta for creating user interfaces. Instead of manually updating the DOM (the page), you describe what your UI should look like, and React figures out the how to update it efficiently.
Building dynamic UIs, single-page apps, dashboards, social feeds, or any interface that changes based on user actions or data.
Building a simple static webpage with no interactivity — plain HTML/CSS is faster to write and load.
The fastest way to start a React project today is with Vite. It replaces the older Create React App and is significantly faster.
# Step 1 — Create the project npm create vite@latest my-app -- --template react # Step 2 — Navigate in cd my-app # Step 3 — Install dependencies npm install # Step 4 — Start development server npm run dev
my-app/ ├── public/ # static files ├── src/ │ ├── App.jsx # main component │ ├── main.jsx # entry point │ └── index.css # global styles ├── index.html └── package.json
JSX lets you write HTML-like syntax inside JavaScript. It's not real HTML — Babel compiles it into React.createElement() calls behind the scenes.
- Every component must return one parent element (wrap in
<></>if needed) - Use
classNameinstead ofclass - Use
htmlForinstead offor - All tags must be closed:
<img />,<br /> - JavaScript expressions go inside
{'{}'}
const name = "Shifat"; const isLoggedIn = true; function App() { return ( <div className="container"> <h1>Hello, {name}!</h1> <p> {isLoggedIn ? "Welcome back 👋" : "Please log in"} </p> <p>2 + 2 = {2 + 2}</p> </div> ); }
{} are your "escape hatch" from JSX back into JavaScript. Put any JS expression inside them — variables, math, ternary operators, function calls.
Day 1 Tasks
Practice TimeCreate a Profile Card
Build a JSX component that shows your name, role, and a short bio. Use at least 3 JSX rules.
Dynamic Greeting
Create a variable with current hour and display "Good Morning", "Good Afternoon", or "Good Evening" conditionally in JSX.
Math in JSX
Display a simple "calculator result" page showing 5 different math operations rendered in JSX.
Components — Building Blocks of React
How to create, nest, and organize reusable UI pieces
A component is just a JavaScript function that returns JSX. React components must start with a capital letter to distinguish them from regular HTML tags.
// Button.jsx function Button() { return <button>Click me!</button>; } export default Button; // Arrow function style (same thing) const Button = () => <button>Click me!</button>; export default Button;
// App.jsx import Button from './Button'; import Header from './Header'; function App() { return ( <div> <Header /> // self-closing = no children <Button></Button> // or with closing tag </div> ); }
Button.jsx exports Button). This keeps your code organised.
Big UIs are built by composing small components together — like LEGO bricks. This makes code reusable, testable, and maintainable.
function Avatar() { return <img src="/avatar.png" className="avatar" />; } function UserName() { return <h2>Shifat</h2>; } function UserCard() { return ( <div className="card"> <Avatar /> // reuse! <UserName /> // reuse! </div> ); }
Header, Footer, Button, Card, Modal, Sidebar — each distinct UI part deserves its own component.
Don't split too early. If a piece of UI is only used once and is 3 lines, keep it in the parent.
Day 2 Tasks
Practice TimeBuild a Navbar Component
Create a Navbar with Logo, Nav Links (Home, About, Contact), and a CTA Button as separate components.
Portfolio Layout
Create Header, HeroSection, ProjectCard, and Footer components. Compose them in App.jsx.
Props — Passing Data to Components
Make components dynamic by feeding them data from outside
Props (short for properties) are how you pass data from a parent component to a child component. Think of them like function arguments for your components.
// Parent passes props like HTML attributes function App() { return ( <div> <Greeting name="Shifat" age={22} /> <Greeting name="Alex" age={25} /> </div> ); } // Child receives props as an object function Greeting(props) { return ( <p> Hello, {props.name}! You are {props.age} years old. </p> ); } // Better: destructure props directly function Greeting({ name, age }) { return <p>Hello, {name}! You are {age}.</p>; }
You can give props default values in case the parent doesn't pass them. The special children prop lets you pass JSX content between component tags.
// Default props with destructuring function Button({ label = "Click me", color = "blue" }) { return ( <button style={{ background: color }}> {label} </button> ); } // children prop — pass JSX between tags function Card({ children, title }) { return ( <div className="card"> <h3>{title}</h3> {children} // renders whatever's between <Card>...</Card> </div> ); } // Usage <Card title="My Project"> <p>This is card content!</p> <Button /> </Card>
Day 3 Tasks
Practice TimeProduct Card Component
Create a ProductCard that accepts name, price, description, and image as props. Render 3 different products.
Reusable Alert Component
Build an Alert component with type prop (success/error/warning) that changes its color and icon accordingly.
Layout Wrapper with children
Build a PageLayout component using the children prop that wraps any content with Header and Footer.
State & Events — Making UI Interactive
useState hook, event handlers, and reactivity explained
useState lets you add reactive data to a component. When state changes, React automatically re-renders the component with the new data.
[currentValue, setterFunction]. Call the setter to update state — never mutate the variable directly!
import { useState } from 'react'; function Counter() { // [state, setter] = useState(initialValue) const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}> +1 </button> <button onClick={() => setCount(0)}> Reset </button> </div> ); }
const [user, setUser] = useState({ name: "Shifat", age: 22 }); // ❌ Wrong — direct mutation user.name = "Alex"; // ✅ Correct — spread operator creates new object setUser({ ...user, name: "Alex" });
React events work like regular DOM events but are named in camelCase and take a function (not a string). Common events: onClick, onChange, onSubmit, onKeyDown.
function EventDemo() { const [text, setText] = useState(""); // event object 'e' gives you access to input value const handleChange = (e) => { setText(e.target.value); }; const handleClick = () => { alert(`You typed: ${text}`); }; return ( <div> <input value={text} onChange={handleChange} placeholder="Type something..." /> <button onClick={handleClick}>Alert</button> <p>Live: {text}</p> </div> ); }
❌
onClick={handleClick()} — runs on render✅
onClick={handleClick} — runs on click
Day 4 Tasks
Practice TimeLike Button
Build a like button that toggles between liked/unliked state and changes its color and count.
Color Picker
Create 5 color buttons. Clicking each changes the background color of a preview box using state.
Word Counter
Build a textarea that displays live word count, character count, and warns when over 100 words.
Shopping Cart Counter
Display 3 products, each with +/- buttons. Show total items and total price in a summary bar.
Lists, Keys & Conditional Rendering
Rendering arrays of data and showing/hiding UI based on conditions
To render a list of items, use JavaScript's .map() method to transform an array of data into an array of JSX elements.
const fruits = ["🍎 Apple", "🍌 Banana", "🍊 Orange"]; function FruitList() { return ( <ul> {fruits.map((fruit, index) => ( <li key={index}>{fruit}</li> ))} </ul> ); } // With objects (more realistic) const users = [ { id: 1, name: "Shifat", role: "Developer" }, { id: 2, name: "Alex", role: "Designer" }, ]; function UserList() { return ( <div> {users.map((user) => ( <div key={user.id}> <strong>{user.name}</strong> - {user.role} </div> ))} </div> ); }
key prop. React uses it to track which items changed. Use a unique ID from your data — avoid using array index for dynamic lists.
Show or hide elements based on conditions. React has several patterns for this.
function Dashboard({ isLoggedIn, isAdmin, notifications }) { return ( <div> // 1. If/else with early return {!isLoggedIn && <p>Please log in.</p>} // 2. Ternary operator {isAdmin ? <AdminPanel /> : <UserPanel /> } // 3. && short-circuit (show if truthy) {notifications.length > 0 && ( <Badge count={notifications.length} /> )} </div> ); }
notifications.length is 0, React renders 0 on screen! Use notifications.length {'>'} 0 && or convert to boolean: !!notifications.length &&
Day 5 Tasks
Practice TimeTodo List
Render a hardcoded array of todos. Each todo shows its text and a "Done" badge if completed.
Filterable Product Grid
Show products filtered by category. Add "All", "Electronics", "Clothing" buttons to filter the list.
useEffect — Side Effects & Data Fetching
Running code after renders, API calls, timers, and cleanups
useEffect runs after the component renders. Use it for anything that isn't pure rendering — API calls, timers, subscriptions, DOM manipulation.
•
[] — run once after first render (like componentDidMount)•
[value] — run after first render + every time value changes• No array — run after every single render (rare, usually a bug)
import { useState, useEffect } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // This runs after render, whenever userId changes async function fetchUser() { const res = await fetch( `https://jsonplaceholder.typicode.com/users/${userId}` ); const data = await res.json(); setUser(data); setLoading(false); } fetchUser(); }, [userId]); // re-run when userId changes if (loading) return <p>Loading...</p>; return <h2>{user.name}</h2>; }
// Return a function to clean up (timers, subscriptions) useEffect(() => { const timer = setInterval(() => { setSeconds(s => s + 1); }, 1000); return () => clearInterval(timer); // cleanup! }, []);
Day 6 Tasks
Practice TimeLive Clock
Build a clock that updates every second using useEffect + setInterval. Include cleanup.
Fetch & Display Posts
Fetch posts from JSONPlaceholder API. Show a loading spinner while fetching, then display the list.
Search with useEffect
Build a search input that fetches results from an API whenever the input value changes (debounce is a bonus).
Forms, Controlled Inputs & Validation
Handling user input, controlled vs uncontrolled components
In React, form inputs are controlled — their value is driven by state, not the DOM. This gives you full control over the data at all times.
function LoginForm() { const [formData, setFormData] = useState({ email: "", password: "", }); const [errors, setErrors] = useState({}); const handleChange = (e) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const validate = () => { const newErrors = {}; if (!formData.email.includes("@")) newErrors.email = "Invalid email"; if (formData.password.length < 6) newErrors.password = "Min 6 characters"; return newErrors; }; const handleSubmit = (e) => { e.preventDefault(); // prevent page reload! const errs = validate(); if (Object.keys(errs).length > 0) { setErrors(errs); } else { console.log("Submitted!", formData); } }; return ( <form onSubmit={handleSubmit}> <input name="email" value={formData.email} onChange={handleChange} /> {errors.email && <span>{errors.email}</span>} <input type="password" name="password" value={formData.password} onChange={handleChange} /> {errors.password && <span>{errors.password}</span>} <button type="submit">Login</button> </form> ); }
Day 7 Tasks
Practice TimeRegistration Form
Build a sign-up form (name, email, password, confirm password) with validation and error messages.
Dynamic Todo Input
Add an input + button to your Day 5 todo list. Typing and pressing Enter or clicking Add creates a new todo.
React Router — Navigation & Pages
Build multi-page SPAs with client-side routing
React Router lets you build multi-page apps without page reloads. The URL changes, but only the component swaps — super fast navigation.
npm install react-router-dom
// main.jsx — wrap app in BrowserRouter import { BrowserRouter } from 'react-router-dom'; ReactDOM.createRoot(document.getElementById('root')).render( <BrowserRouter> <App /> </BrowserRouter> ); // App.jsx — define routes import { Routes, Route, Link } from 'react-router-dom'; import Home from './pages/Home'; import About from './pages/About'; import UserPage from './pages/UserPage'; function App() { return ( <div> <nav> <Link to="/">Home</Link> <Link to="/about">About</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> // Dynamic route with URL param <Route path="/user/:id" element={<UserPage />} /> <Route path="*" element={<h1>404 Not Found</h1>} /> </Routes> </div> ); } // UserPage.jsx — reading URL params import { useParams } from 'react-router-dom'; function UserPage() { const { id } = useParams(); return <h1>User ID: {id}</h1>; }
Day 8 Tasks
Practice TimeMulti-page Portfolio
Create Home, About, Projects, and Contact pages with a working Navbar using React Router.
Blog with Dynamic Routes
List 5 blog posts. Clicking any opens /blog/:id which fetches and shows that post from JSONPlaceholder.
Context API, useReducer & Custom Hooks
Global state management and building reusable logic
Context solves prop drilling — passing props down through many layers of components just to reach a deeply nested child. With Context, any component can directly access shared state.
// ThemeContext.jsx import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [theme, setTheme] = useState('dark'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } // Custom hook for easy access export const useTheme = () => useContext(ThemeContext); // Any component — no prop drilling! function ToggleButton() { const { theme, setTheme } = useTheme(); return ( <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark') }> Switch to {theme === 'dark' ? 'Light' : 'Dark'} </button> ); }
Custom hooks are functions starting with use that extract and reuse stateful logic across components. They're one of React's most powerful patterns.
// hooks/useFetch.js — reusable data fetching 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 }; } // Use it anywhere — clean and readable! function Posts() { const { data, loading } = useFetch( 'https://jsonplaceholder.typicode.com/posts' ); if (loading) return <p>Loading...</p>; return <ul>{data.map(p => <li key={p.id}>{p.title}</li>)}</ul>; }
Day 9 Tasks
Practice TimeDark Mode Context
Implement a global dark/light mode toggle using Context API. All components should respond to the change.
useLocalStorage Hook
Build a custom hook that syncs state to localStorage. Use it for a persistent todo list that survives refresh.
Final Project — Full React App
Bring everything together: a complete Task Manager app
Build a full-featured Task Manager that combines everything you've learned. This project will demonstrate your React skills to anyone who sees your portfolio.
- Add, edit, and delete tasks (CRUD)
- Filter tasks by status: All / Active / Completed
- Mark tasks as complete with a checkbox
- Task priority levels (High, Medium, Low) with colors
- Persist tasks to localStorage with a custom hook
- Dark/Light mode toggle with Context API
- Multi-page layout with React Router
src/ ├── context/ │ └── ThemeContext.jsx # dark mode (Day 9) ├── hooks/ │ ├── useLocalStorage.js # persistence (Day 9) │ └── useTasks.js # task logic custom hook ├── pages/ │ ├── Home.jsx # task list page │ └── Stats.jsx # task statistics page ├── components/ │ ├── TaskForm.jsx # add/edit form (Day 7) │ ├── TaskList.jsx # list + filter (Day 5) │ ├── TaskItem.jsx # single task card │ └── Navbar.jsx # nav with router links (Day 8) └── App.jsx # routes setup
// hooks/useTasks.js function useTasks() { const [tasks, setTasks] = useLocalStorage('tasks', []); const addTask = (text, priority) => { setTasks([...tasks, { id: Date.now(), text, priority, completed: false }]); }; const toggleTask = (id) => { setTasks(tasks.map(t => t.id === id ? { ...t, completed: !t.completed } : t )); }; const deleteTask = (id) => setTasks(tasks.filter(t => t.id !== id)); return { tasks, addTask, toggleTask, deleteTask }; }
Congratulations on completing 10 days! Here's what to learn next to level up.
Learn Zustand or Redux Toolkit for complex global state in larger apps.
Learn TanStack Query (React Query) for caching, loading, and syncing server data.
Learn Tailwind CSS for rapid utility-first styling, or styled-components for CSS-in-JS.
Learn Next.js for SSR, SEO, and full-stack React apps — it's the industry standard.
Day 10 Final Tasks
CapstoneBuild the Task Manager
Complete all 7 features. Deploy it to Vercel. Add it to your portfolio at shifat.dev.
Write a Post About It
Share what you built and what you learned on X (@Web3DecoderX) or your YouTube channel. Build in public!
Bonus: Add Animations
Integrate Framer Motion to animate task additions, deletions, and page transitions.