What is React?
React is a JavaScript library for building user interfaces, developed by Facebook. It allows you to create reusable UI components and efficiently update the DOM when data changes.
Key Features:
- Component-Based : Build encapsulated components that manage their own state
- Declarative : Design simple views for each state, React efficiently updates and renders components
- Learn Once, Write Anywhere : Create web apps, mobile apps (React Native), and more
Setup & Installation
# Create a new React app
npx create-react-app my-app
# Navigate to the project
cd my-app
# Start development server
npm start
Project Structure:
my-app/
├── node_modules/
├── public/
│ └── index.html
├── src/
│ ├── App.js # Main component
│ ├── App.css # Styles
│ ├── index.js # Entry point
│ └── index.css
└── package.json
JSX Syntax
JSX (JavaScript XML) allows you to write HTML-like code in JavaScript.
// JSX Example
const element = <h1>Hello, World!</h1>;
---
// JSX with expressions
const name = "John";
const greeting = <h1>Hello, {name}!</h1>;
// JSX with attributes
const image = <img src="photo.jpg" alt="Profile" />;
// JSX with multiple elements (must have one parent)
const card = (
<div className="card">
<h2>Title</h2>
<p>Description</p>
</div>
);
// JSX Rules:
// - Use className instead of class
// - Use camelCase for attributes (onClick, onChange)
// - Close all tags (<img />, <input />)
// - Use {} for JavaScript expressions
Components
Components are the building blocks of React applications. They come in two types: Functional and Class components (modern React favors functional components).
Functional Component
// Simple functional component
function Welcome() {
return <h1>Welcome to React!</h1>;
}
// Arrow function component
const Greeting = () => {
return <h1>Hello!</h1>;
};
// Component with JavaScript logic
function UserCard() {
const user = {
name: "Alice",
age: 25
};
return (
<div>
<h2>{user.name}</h2>
<p>Age: {user.age}</p>
</div>
);
}
Class Component (Legacy)
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Welcome to React!</h1>;
}
}
Props
Props (properties) allow you to pass data from parent to child components. They are read-only.
// Parent component passing props
function App() {
return (
<div>
<Greeting name="Alice" age={25} />
<Greeting name="Bob" age={30} />
</div>
);
}
// Child component receiving props
function Greeting(props) {
return (
<div>
<h2>Hello, {props.name}!</h2>
<p>Age: {props.age}</p>
</div>
);
}
// Using destructuring (cleaner)
function Greeting({ name, age }) {
return (
<div>
<h2>Hello, {name}!</h2>
<p>Age: {age}</p>
</div>
);
}
// Default props
function Greeting({ name = "Guest", age = 0 }) {
return <h2>Hello, {name}! Age: {age}</h2>;
}
// Props children
function Card({ children }) {
return <div className="card">{children}</div>;
}
// Usage
<Card>
<h2>Title</h2>
<p>Content here</p>
</Card>
State
State is data that changes over time within a component. Use the useState hook to manage state in functional components.
import { useState } from 'react';
function Counter() {
// Declare state variable
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
// Multiple state variables
function UserForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="number"
value={age}
onChange={(e) => setAge(e.target.value)}
placeholder="Age"
/>
</div>
);
}
// State with objects
function UserProfile() {
const [user, setUser] = useState({
name: 'Alice',
age: 25,
email: 'alice@example.com'
});
const updateName = (newName) => {
setUser({ ...user, name: newName }); // Spread operator to maintain other properties
};
return (
<div>
<h2>{user.name}</h2>
<button onClick={() => updateName('Bob')}>Change Name</button>
</div>
);
}
Event Handling
React events are named using camelCase and pass functions as handlers.
function EventExamples() {
// Click event
const handleClick = () => {
alert('Button clicked!');
};
// Event with parameter
const greet = (name) => {
alert(`Hello, ${name}!`);
};
// Form submission
const handleSubmit = (e) => {
e.preventDefault(); // Prevent page reload
console.log('Form submitted');
};
// Input change
const handleChange = (e) => {
console.log('Input value:', e.target.value);
};
// Mouse events
const handleMouseEnter = () => {
console.log('Mouse entered!');
};
return (
<div>
<button onClick={handleClick}>Click Me</button>
<button onClick={() => greet('Alice')}>Greet Alice</button>
<form onSubmit={handleSubmit}>
<input onChange={handleChange} />
<button type="submit">Submit</button>
</form>
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={() => console.log('Mouse left!')}
>
Hover over me
</div>
</div>
);
}
// Common Events:
// onClick, onChange, onSubmit, onFocus, onBlur
// onMouseEnter, onMouseLeave, onKeyDown, onKeyUp
Conditional Rendering
Render components based on conditions using JavaScript operators.
function LoginStatus({ isLoggedIn }) {
// Using if-else
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
} else {
return <h1>Please sign in</h1>;
}
}
// Using ternary operator
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? <h1>Welcome!</h1> : <h1>Please log in</h1>}
</div>
);
}
// Using && operator (for single condition)
function Notification({ hasMessages }) {
return (
<div>
<h1>Dashboard</h1>
{hasMessages && <p>You have new messages!</p>}
</div>
);
}
// Conditional rendering with multiple conditions
function UserPanel({ user, isAdmin }) {
return (
<div>
{user ? (
<div>
<h2>{user.name}</h2>
{isAdmin && <button>Admin Panel</button>}
</div>
) : (
<button>Login</button>
)}
</div>
);
}
// Switch-case alternative
function StatusMessage({ status }) {
const getMessage = () => {
switch(status) {
case 'loading': return 'Loading...';
case 'success': return 'Success!';
case 'error': return 'Error occurred';
default: return 'Unknown status';
}
};
return <p>{getMessage()}</p>;
}
Lists & Keys
Render arrays of data using map() and assign unique keys to list items.
function TodoList() {
const todos = [
{ id: 1, text: 'Learn React', completed: false },
{ id: 2, text: 'Build a project', completed: false },
{ id: 3, text: 'Deploy app', completed: true }
];
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.text} {todo.completed && '✓'}
</li>
))}
</ul>
);
}
// Keys help React identify which items have changed
// Use unique IDs, not array indexes (when possible)
// More complex example
function UserList() {
const users = [
{ id: 1, name: 'Alice', role: 'Admin' },
{ id: 2, name: 'Bob', role: 'User' },
{ id: 3, name: 'Charlie', role: 'User' }
];
return (
<div>
{users.map((user) => (
<div key={user.id} className="user-card">
<h3>{user.name}</h3>
<span>{user.role}</span>
</div>
))}
</div>
);
}
// Filtering lists
function ProductList() {
const products = [
{ id: 1, name: 'Laptop', price: 999, inStock: true },
{ id: 2, name: 'Phone', price: 699, inStock: false },
{ id: 3, name: 'Tablet', price: 499, inStock: true }
];
return (
<div>
<h2>Available Products</h2>
{products
.filter(product => product.inStock)
.map(product => (
<div key={product.id}>
<h3>{product.name}</h3>
<p>${product.price}</p>
</div>
))}
</div>
);
}
Hooks Overview
Hooks let you use state and other React features in functional components.
Common Hooks:
- useState : Manage state
- useEffect : Side effects (API calls, subscriptions)
- useContext : Access context values
- useRef : Access DOM elements or persist values
- useMemo : Memoize expensive calculations
- useCallback : Memoize functions
import { useState, useEffect, useRef, useMemo } from 'react';
// useState - covered in State section
const [count, setCount] = useState(0);
// useRef - Access DOM elements
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
// useMemo - Optimize performance
function ExpensiveComponent({ numbers }) {
const sum = useMemo(() => {
console.log('Calculating sum...');
return numbers.reduce((a, b) => a + b, 0);
}, [numbers]); // Only recalculate when numbers change
return <div>Sum: {sum}</div>;
}
useEffect Hook
useEffect handles side effects like data fetching, subscriptions, and DOM manipulation.
import { useState, useEffect } from 'react';
// Run on every render
function Example1() {
useEffect(() => {
console.log('Component rendered');
});
}
// Run once on mount (empty dependency array)
function Example2() {
useEffect(() => {
console.log('Component mounted');
}, []);
}
// Run when specific values change
function Example3() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Count changed:', count);
}, [count]); // Only runs when count changes
}
// Cleanup function
function Example4() {
useEffect(() => {
const timer = setInterval(() => {
console.log('Tick');
}, 1000);
// Cleanup when component unmounts
return () => {
clearInterval(timer);
};
}, []);
}
// Practical example: Fetch data from API
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetch(`https://api.example.com/users/${userId}`)
.then(response => response.json())
.then(data => {
setUser(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, [userId]); // Re-fetch when userId changes
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>No user found</div>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
// Document title update
function PageTitle() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
Forms & Controlled Components
In React, form elements are controlled by component state.
import { useState } from 'react';
// Simple form
function LoginForm() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log('Login:', { username, password });
// API call here
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}
// Complex form with validation
function RegistrationForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
age: '',
country: 'USA',
subscribe: false
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value
});
};
const validate = () => {
const newErrors = {};
if (!formData.name) newErrors.name = 'Name is required';
if (!formData.email) newErrors.email = 'Email is required';
if (formData.age < 18) newErrors.age = 'Must be 18 or older';
return newErrors;
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = validate();
if (Object.keys(newErrors).length === 0) {
console.log('Form submitted:', formData);
// Submit to API
} else {
setErrors(newErrors);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<input
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Name"
/>
{errors.name && <span className="error">{errors.name}</span>}
</div>
<div>
<input
name="email"
type="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
/>
{errors.email && <span className="error">{errors.email}</span>}
</div>
<div>
<input
name="age"
type="number"
value={formData.age}
onChange={handleChange}
placeholder="Age"
/>
{errors.age && <span className="error">{errors.age}</span>}
</div>
<div>
<select name="country" value={formData.country} onChange={handleChange}>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Canada">Canada</option>
</select>
</div>
<div>
<label>
<input
name="subscribe"
type="checkbox"
checked={formData.subscribe}
onChange={handleChange}
/>
Subscribe to newsletter
</label>
</div>
<button type="submit">Register</button>
</form>
);
}
// Textarea example
function CommentForm() {
const [comment, setComment] = useState('');
return (
<form>
<textarea
value={comment}
onChange={(e) => setComment(e.target.value)}
placeholder="Write a comment..."
rows="4"
/>
<p>Character count: {comment.length}</p>
</form>
);
}
Component Lifecycle
Understanding when components mount, update, and unmount.
import { useState, useEffect } from 'react';
function LifecycleDemo() {
const [count, setCount] = useState(0);
// 1. Component Mounts (runs once)
useEffect(() => {
console.log('Component mounted');
// Cleanup when component unmounts
return () => {
console.log('Component will unmount');
};
}, []);
// 2. Component Updates (runs when count changes)
useEffect(() => {
console.log('Count updated:', count);
}, [count]);
// 3. Every render
useEffect(() => {
console.log('Component rendered');
});
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
// Lifecycle phases:
// 1. Mounting: Component is created and inserted into the DOM
// 2. Updating: Component re-renders due to state/props changes
// 3. Unmounting: Component is removed from the DOM
Quick Reference
Component Structure
import { useState, useEffect } from 'react';
function MyComponent({ prop1, prop2 }) {
// 1. Hooks (at the top)
const [state, setState] = useState(initialValue);
useEffect(() => {
// Side effects
}, [dependencies]);
// 2. Event handlers
const handleClick = () => {
// Handle event
};
// 3. Helper functions
const calculateSomething = () => {
// Logic
};
// 4. Return JSX
return (
<div>
<h1>{prop1}</h1>
<button onClick={handleClick}>Click</button>
</div>
);
}
export default MyComponent;
Common Patterns
1. Toggle State
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);
2. Update Object State
const [user, setUser] = useState({ name: '', age: 0 });
setUser({ ...user, name: 'Alice' });
3. Update Array State
const [items, setItems] = useState([]);
setItems([...items, newItem]); // Add
setItems(items.filter(item => item.id !== id)); // Remove
4. Conditional Class
<div className={isActive ? 'active' : 'inactive'}>Content</div>
5. Inline Styles
<div style={{ color: 'red', fontSize: '20px' }}>Text</div>
Best Practices
- Component Names : Use PascalCase (MyComponent)
- Props Naming : Use camelCase (onClick, userName)
- State Updates : Never mutate state directly, use setter functions
- Keys in Lists : Use unique IDs, not array indexes (when possible)
- Event Handlers : Use arrow functions or bind methods
- Component Size : Keep components small and focused
- File Organization : One component per file
- Prop Types : Use TypeScript or PropTypes for type checking
Useful Snippets
Loading State
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
Modal Toggle
const [showModal, setShowModal] = useState(false);
const openModal = () => setShowModal(true);
const closeModal = () => setShowModal(false);
Form Input Handler
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
Complete Mini-App Example
Here’s a complete todo app demonstrating multiple concepts:
import { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const [filter, setFilter] = useState('all'); // all, active, completed
// Add todo
const addTodo = (e) => {
e.preventDefault();
if (input.trim()) {
setTodos([
...todos,
{ id: Date.now(), text: input, completed: false }
]);
setInput('');
}
};
// Toggle todo completion
const toggleTodo = (id) => {
setTodos(
todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
// Delete todo
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
// Filter todos
const getFilteredTodos = () => {
switch(filter) {
case 'active':
return todos.filter(todo => !todo.completed);
case 'completed':
return todos.filter(todo => todo.completed);
default:
return todos;
}
};
const filteredTodos = getFilteredTodos();
const activeCount = todos.filter(t => !t.completed).length;
return (
<div className="todo-app">
<h1>Todo List</h1>
{/* Add Todo Form */}
<form onSubmit={addTodo}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="What needs to be done?"
/>
<button type="submit">Add</button>
</form>
{/* Filter Buttons */}
<div className="filters">
<button
onClick={() => setFilter('all')}
className={filter === 'all' ? 'active' : ''}
>
All
</button>
<button
onClick={() => setFilter('active')}
className={filter === 'active' ? 'active' : ''}
>
Active
</button>
<button
onClick={() => setFilter('completed')}
className={filter === 'completed' ? 'active' : ''}
>
Completed
</button>
</div>
{/* Todo List */}
<ul className="todo-list">
{filteredTodos.length === 0 ? (
<li className="empty">No todos to display</li>
) : (
filteredTodos.map(todo => (
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))
)}
</ul>
{/* Footer */}
<div className="footer">
<span>{activeCount} items left</span>
</div>
</div>
);
}
export default TodoApp;
Next Steps
After mastering these basics:
- React Router — Navigation and routing
- Context API — Global state management
- Redux/Zustand — Advanced state management
- Custom Hooks — Reusable logic
- Performance Optimization — memo, useMemo, useCallback
- TypeScript — Type safety
- Testing — Jest and React Testing Library
- API Integration — Axios, Fetch API, React Query
- Styling — CSS Modules, Styled Components, Tailwind
- Build Tools — Vite, Webpack
Resources:
Happy Coding! 🚀
Last Updated: January 17, 2026

Top comments (0)