React — Practical Guide (Cover & TOC)
React: A modern JavaScript library for building composable user interfaces.
Contents (10 pages): 1. Overview & JSX 2. Components & Props 3. State & useState 4.
useEffect & lifecycle 5. Context & Hooks
6. Routing & Forms 7. Lists, Keys & Conditional Rendering 8. Performance & Testing 9. RTK &
TypeScript 10. Build, Deploy & Exercises
Author: (Your Name) — Course: Frontend Development
Tip: Run the examples locally using Create React App, Vite, or your preferred starter.
Page 1 — React Practical Guide (10-page)
Overview & JSX
React renders UI as a function of state and props. It uses a virtual DOM to batch updates and
update the real DOM efficiently.
JSX is a syntax extension that allows HTML-like code inside JavaScript. It compiles to
React.createElement calls.
jsx example:
// index.jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
const App = () => <h1>Hello React!</h1>;
createRoot(document.getElementById('root')).render(<App />);
JSX expressions use curly braces: { expression }. Use className for CSS classes.
Page 2 — React Practical Guide (10-page)
Components & Props
Components are reusable UI building blocks. Prefer function components with hooks for modern
code.
Props are values passed from parent to child; they are read-only inside the child component.
jsx example:
function UserCard({ user }) {
return (
<div className="card">
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
// Usage: <UserCard user={{name: 'Priya', email: 'p@x.com'}} />
Keep components focused (single responsibility). Small components are easier to test.
Page 3 — React Practical Guide (10-page)
State & useState
useState lets function components hold state. Initialize with a value and use the setter to
update.
Prefer multiple useState calls for unrelated pieces of state rather than one large object.
jsx example:
import { useState } from 'react';
function Counter(){
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
}
Use the updater form setState(prev => next) when new state depends on previous state.
Page 4 — React Practical Guide (10-page)
useEffect & Lifecycle
useEffect handles side effects: data fetching, subscriptions, and timers. Add a cleanup
function to avoid leaks.
The dependency array controls when the effect runs: [] runs once on mount; [dep] runs when dep
changes.
jsx example:
import { useEffect, useState } from 'react';
function Clock(){
const [time, setTime] = useState(new Date());
useEffect(() => {
const id = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(id);
}, []);
return <div>{time.toLocaleTimeString()}</div>;
}
jsx example:
useEffect(() => {
let cancelled = false;
fetch(`/api/search?q=${query}`)
.then(r => r.json())
.then(data => { if(!cancelled) setData(data); });
return () => { cancelled = true; };
}, [query]);
Don't forget to include dependencies; ESLint plugin react-hooks helps.
Page 5 — React Practical Guide (10-page)
Context & Custom Hooks
Context provides a way to pass data through the tree without props drilling. Use it for
theming, locale, or auth state.
Custom hooks let you encapsulate reusable logic (e.g., useFetch, useToggle).
jsx example:
const ThemeContext = React.createContext('light');
function App(){
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(){
const theme = React.useContext(ThemeContext);
return <div className={theme}>Toolbar</div>;
}
jsx example:
function useToggle(initial=false){
const [on, setOn] = useState(initial);
const toggle = () => setOn(v => !v);
return [on, toggle];
}
Context is not ideal for high-frequency updates; prefer local state or state libraries.
Page 6 — React Practical Guide (10-page)
Routing & Forms
React Router (react-router-dom) provides client-side routing. Use BrowserRouter and Routes to
define routes.
Forms can be controlled (React state drives inputs) or uncontrolled (refs). For complex forms,
use React Hook Form.
jsx example:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
<BrowserRouter>
<nav><Link to="/">Home</Link></nav>
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/login" element={<Login/>} />
</Routes>
</BrowserRouter>
jsx example:
function Login(){
const [email, setEmail] = useState('');
const [pass, setPass] = useState('');
return (
<form onSubmit={e => { e.preventDefault(); /* auth */ }}>
<label>Email<input value={email} onChange={e => setEmail(e.target.value)} /></label>
<label>Password<input type="password" value={pass} onChange={e =>
setPass(e.target.value)} /></label>
<button type="submit">Login</button>
</form>
);
}
Debounce heavy validations; keep UX responsive for inputs like search.
Page 7 — React Practical Guide (10-page)
Lists, Keys & Conditional Rendering
Render dynamic lists with map and provide a stable key prop (usually an id). Conditional
rendering controls what to show based on state.
Avoid using array index as key when the list order can change.
jsx example:
const todos = [{id:1, text:'Buy milk'}, {id:2, text:'Walk dog'}];
<ul>{todos.map(t => <li key={t.id}>{t.text}</li>)}</ul>
{isLoading ? <Spinner/> : <Content/>}
Stable keys prevent unnecessary re-mounts and preserve input state inside list items.
Page 8 — React Practical Guide (10-page)
Performance, Testing & Tooling
Optimize with React.memo, useMemo, and useCallback when you know re-renders are expensive.
Virtualize long lists.
Test with Jest + React Testing Library. Use msw for mocking network requests in tests.
jsx example:
const Item = React.memo(function Item({value}){ return <div>{value}</div>; });
const memoized = useCallback(() => doWork(x), [x]);
const cached = useMemo(() => heavyCalc(data), [data]);
js example:
import { render, screen } from '@testing-library/react';
test('renders greeting', () => {
render(<Greeting name="A"/>);
expect(screen.getByText(/A/)).toBeInTheDocument();
});
Measure before optimizing. Use Profiler and Lighthouse for performance insights.
Page 9 — React Practical Guide (10-page)
RTK, TypeScript & Deploy
Use Redux Toolkit for scalable global state. Prefer RTK Query for server-state caching.
TypeScript brings static types for safer refactors.
Build with npm run build and deploy to Vercel/Netlify. Use environment variables for secrets.
js example:
// slice example (RTK)
import { createSlice } from '@reduxjs/toolkit';
const slice = createSlice({ name:'items', initialState:[], reducers:{ add:(s,a)=>{
s.push(a.payload) } } });
export const { add } = slice.actions;
tsx example:
type Props = { name: string };
function Hello({ name }: Props){ return <h1>{name}</h1>; }
Exercise: Build a 3-page app with routing, context auth, and a small RTK slice. Deploy it
and share the link.
Page 10 — React Practical Guide (10-page)