Learn React fundamentals, hooks, state management, and component architecture.
React is a JavaScript library for building user interfaces. It's component-based, declarative, and efficient.
function Welcome(props) { return <h1>Hello, {props.name}!</h1>; }
Loading diagram...
function Greeting({ name }) { return <h1>Hello, {name}!</h1>; }
class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}!</h1>; } }
const Greeting = ({ name }) => { return <h1>Hello, {name}!</h1>; };
function UserCard({ user, onEdit }) { return ( <div> <h2>{user.name}</h2> <p>{user.email}</p> <button onClick={() => onEdit(user.id)}>Edit</button> </div> ); }
function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
{}
function Example() { const name = 'React'; const isActive = true; return ( <div className="container"> <h1>Welcome to {name}</h1> <button disabled={!isActive}>{isActive ? 'Click me' : 'Disabled'}</button> </div> ); }
function Form() { const [input, setInput] = useState(''); const handleSubmit = (e) => { e.preventDefault(); console.log('Form submitted:', input); }; const handleChange = (e) => { setInput(e.target.value); }; return ( <form onSubmit={handleSubmit}> <input value={input} onChange={handleChange} placeholder="Type something..." /> <button type="submit">Submit</button> </form> ); }
function Greeting({ user }) { if (!user) { return <div>Please log in</div>; } return ( <div> <h1>Welcome back, {user.name}!</h1> {user.isAdmin && <AdminPanel />} </div> ); }
function TodoList({ todos }) { return ( <ul> {todos.map((todo) => ( <li key={todo.id}>{todo.text}</li> ))} </ul> ); }
function App() { return ( <div> <Header /> <Main> <Sidebar /> <Content /> </Main> <Footer /> </div> ); }
Learn about functional and class components, props, and composition.
Master useState, useEffect, and custom hooks for state management.
Handle API calls, loading states, and error handling.
Explore local state, context, and advanced patterns.
Custom hooks allow you to extract component logic into reusable functions.
function useCounter(initialValue = 0) { const [count, setCount] = useState(initialValue); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); const reset = () => setCount(initialValue); return { count, increment, decrement, reset }; }
Loading diagram...
function DataFetcher({ render }) { const [data, setData] = useState(null); useEffect(() => { fetchData().then(setData); }, []); return render(data); } // Usage <DataFetcher render={(data) => <UserList users={data} />} />;
function withLoading(Component) { return function WrappedComponent(props) { const [loading, setLoading] = useState(true); useEffect(() => { // Simulate loading setTimeout(() => setLoading(false), 1000); }, []); if (loading) return <div>Loading...</div>; return <Component {...props} />; }; } const UserListWithLoading = withLoading(UserList);
function Tabs({ children }) { const [activeTab, setActiveTab] = useState(0); return ( <TabsContext.Provider value={{ activeTab, setActiveTab }}>{children}</TabsContext.Provider> ); } Tabs.List = function TabsList({ children }) { return <div className="tabs-list">{children}</div>; }; Tabs.Tab = function Tab({ children, index }) { const { activeTab, setActiveTab } = useContext(TabsContext); return ( <button className={activeTab === index ? 'active' : ''} onClick={() => setActiveTab(index)}> {children} </button> ); }; Tabs.Panel = function TabPanel({ children, index }) { const { activeTab } = useContext(TabsContext); if (activeTab !== index) return null; return <div className="tab-panel">{children}</div>; }; // Usage <Tabs> <Tabs.List> <Tabs.Tab index={0}>Tab 1</Tabs.Tab> <Tabs.Tab index={1}>Tab 2</Tabs.Tab> </Tabs.List> <Tabs.Panel index={0}>Content 1</Tabs.Panel> <Tabs.Panel index={1}>Content 2</Tabs.Panel> </Tabs>;
const ThemeContext = createContext(); function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); const toggleTheme = () => { setTheme((prev) => (prev === 'light' ? 'dark' : 'light')); }; return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>; } function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within ThemeProvider'); } return context; }
class ErrorBoundary extends React.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 by boundary:', error, errorInfo); } render() { if (this.state.hasError) { return ( <div className="error-boundary"> <h2>Something went wrong</h2> <details> <summary>Error details</summary> <pre>{this.state.error?.toString()}</pre> </details> </div> ); } return this.props.children; } }
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; test('counter increments when button is clicked', () => { render(<Counter />); const button = screen.getByRole('button'); userEvent.click(button); expect(screen.getByText('Count: 1')).toBeInTheDocument(); }); test('renders user name', () => { const user = { name: 'John Doe' }; render(<UserProfile user={user} />); expect(screen.getByText('John Doe')).toBeInTheDocument(); });
import { Profiler } from 'react'; function onRenderCallback(id, phase, actualDuration, baseDuration, startTime, commitTime) { console.log(`Component ${id} took ${actualDuration}ms to render`); } <Profiler id="App" onRender={onRenderCallback}> <App /> </Profiler>;
import { StrictMode } from 'react'; <StrictMode> <App /> </StrictMode>;
import { lazy, Suspense } from 'react'; const LazyComponent = lazy(() => import('./LazyComponent')); function App() { return ( <Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </Suspense> ); }
import { lazy } from 'react'; import { Routes, Route } from 'react-router-dom'; const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); const Contact = lazy(() => import('./pages/Contact')); function App() { return ( <Suspense fallback={<div>Loading...</div>}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/contact" element={<Contact />} /> </Routes> </Suspense> ); }
import { Profiler } from 'react'; function onRenderCallback(id, phase, actualDuration, baseDuration, startTime, commitTime) { // Log performance metrics console.log({ id, phase, actualDuration, baseDuration, startTime, commitTime, }); } <Profiler id="App" onRender={onRenderCallback}> <App /> </Profiler>;
# Analyze bundle size npm install --save-dev webpack-bundle-analyzer # Add to webpack config const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] };
function SearchInput({ onSearch }) { return ( <div> <label htmlFor="search">Search:</label> <input id="search" type="text" aria-describedby="search-help" placeholder="Enter search terms..." /> <div id="search-help">Type keywords to find relevant content</div> </div> ); }
function MenuItem({ children, onSelect }) { const handleKeyDown = (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect(); } }; return ( <div role="menuitem" tabIndex={0} onKeyDown={handleKeyDown} onClick={onSelect}> {children} </div> ); }