React Complete Guide for Beginners
Welcome to the complete React tutorial! React is a powerful JavaScript library for building user interfaces, created and maintained by Facebook (Meta). This guide will take you from zero to hero in React development.
Table of Contents
- What is React?
- Getting Started
- Components and JSX
- Props: Passing Data
- State Management
- Hooks Deep Dive
- Event Handling
- Conditional Rendering
- Lists and Keys
- Real-World Example
What is React?
React is a JavaScript library for building user interfaces, particularly single-page applications where you need a fast, interactive user experience. React was created by Jordan Walke, a software engineer at Facebook, and was first deployed on Facebook's newsfeed in 2011.
Key Features of React
- Component-Based: Build encapsulated components that manage their own state
- Declarative: Design simple views for each state in your application
- Learn Once, Write Anywhere: Use React for web, mobile (React Native), and even VR
- Virtual DOM: Efficient rendering and updates
- Unidirectional Data Flow: Makes debugging easier and code more predictable
Why Learn React?
- High Demand: React is one of the most in-demand skills in web development
- Strong Ecosystem: Massive community, extensive libraries, and tools
- Performance: Virtual DOM makes React applications fast
- Career Growth: Used by Facebook, Netflix, Airbnb, Instagram, and thousands more
Getting Started
Prerequisites
Before learning React, you should have a basic understanding of:
- HTML & CSS
- JavaScript (ES6+ features like arrow functions, destructuring, spread operator)
- DOM manipulation basics
Setting Up Your Environment
Option 1: Create React App (Recommended for Beginners)
# Create a new React app
npx create-react-app my-react-app
# Navigate to the project
cd my-react-app
# Start the development server
npm start
Option 2: Online Playground
Use online editors like:
- CodeSandbox (https://codesandbox.io)
- CodePen (https://codepen.io)
- StackBlitz (https://stackblitz.com)
Project Structure
After creating a React app, you'll see this structure:
my-react-app/
āāā node_modules/
āāā public/
ā āāā index.html
ā āāā favicon.ico
āāā src/
ā āāā App.js
ā āāā App.css
ā āāā index.js
ā āāā index.css
āāā package.json
āāā README.md
Components and JSX
What are Components?
Components are the building blocks of React applications. They are reusable pieces of UI that can have their own logic and styling.
Functional Components
Modern React uses functional components with hooks:
// Simple functional component
function Welcome() {
return <h1>Hello, World!</h1>;
}
// Or using arrow function
const Welcome = () => {
return <h1>Hello, World!</h1>;
};
export default Welcome;
JSX Syntax
JSX (JavaScript XML) allows you to write HTML-like code in JavaScript:
function Profile() {
const user = {
name: "Sarah Johnson",
imageUrl: "https://i.imgur.com/yXOvdOSs.jpg",
imageSize: 90
};
return (
<div className="profile">
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize,
borderRadius: '50%'
}}
/>
</div>
);
}
JSX Rules
- Single Parent Element: Must return one parent element
// ā
Correct
function MyComponent() {
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
}
// ā Wrong
function MyComponent() {
return (
<h1>Title</h1>
<p>Content</p>
);
}
// ā
Use Fragment
function MyComponent() {
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
}
- Close All Tags: Self-closing tags must have
/>
<img src="image.jpg" alt="Description" />
<br />
<input type="text" />
- className Instead of class: Use
classNamefor CSS classes
<div className="container">Content</div>
- Curly Braces for JavaScript: Use
{}to embed JavaScript
const name = "React";
return <h1>Welcome to {name}</h1>;
Props: Passing Data
Props (properties) allow you to pass data from parent to child components.
Basic Props
// Child component receiving props
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Parent component passing props
function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
<Welcome name="Charlie" />
</div>
);
}
Destructuring Props
// Cleaner way using destructuring
function Welcome({ name, age, city }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
<p>City: {city}</p>
</div>
);
}
function App() {
return <Welcome name="Alice" age={25} city="New York" />;
}
Props with Objects
function UserCard({ user }) {
return (
<div className="user-card">
<img src={user.avatar} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
<p>{user.role}</p>
</div>
);
}
function App() {
const userData = {
name: "Sarah Johnson",
email: "sarah@example.com",
role: "Developer",
avatar: "https://i.imgur.com/avatar.jpg"
};
return <UserCard user={userData} />;
}
Props.children
Special prop that contains content between component tags:
function Card({ children, title }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="card-content">
{children}
</div>
</div>
);
}
function App() {
return (
<Card title="Welcome">
<p>This is the card content</p>
<button>Click me</button>
</Card>
);
}
State Management
State allows components to create and manage their own data. When state changes, the component re-renders.
useState Hook
The most fundamental React hook for managing state:
import { useState } from 'react';
function Counter() {
// Declare state variable
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</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 UserProfile() {
const [name, setName] = useState('John');
const [age, setAge] = useState(25);
const [email, setEmail] = useState('john@example.com');
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Email: {email}</p>
</div>
);
}
State with Objects
function UserForm() {
const [user, setUser] = useState({
firstName: '',
lastName: '',
email: ''
});
const handleChange = (e) => {
setUser({
...user,
[e.target.name]: e.target.value
});
};
return (
<form>
<input
name="firstName"
value={user.firstName}
onChange={handleChange}
placeholder="First Name"
/>
<input
name="lastName"
value={user.lastName}
onChange={handleChange}
placeholder="Last Name"
/>
<input
name="email"
value={user.email}
onChange={handleChange}
placeholder="Email"
/>
</form>
);
}
State with Arrays
function TodoList() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const addTodo = () => {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input }]);
setInput('');
}
};
const removeTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add a todo"
/>
<button onClick={addTodo}>Add</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => removeTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
Hooks Deep Dive
useEffect Hook
useEffect lets you perform side effects in function components (data fetching, subscriptions, manual DOM manipulation).
Basic useEffect
import { useState, useEffect } from 'react';
function DocumentTitle() {
const [count, setCount] = useState(0);
useEffect(() => {
// This runs after every render
document.title = `You clicked ${count} times`;
});
return (
<button onClick={() => setCount(count + 1)}>
Click me
</button>
);
}
useEffect with Dependencies
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// This runs only when userId changes
setLoading(true);
fetch(`https://api.example.com/users/${userId}`)
.then(response => response.json())
.then(data => {
setUser(data);
setLoading(false);
});
}, [userId]); // Dependency array
if (loading) return <p>Loading...</p>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
useEffect Cleanup
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(s => s + 1);
}, 1000);
// Cleanup function
return () => {
clearInterval(interval);
};
}, []); // Empty array = run once on mount
return <p>Seconds: {seconds}</p>;
}
useEffect Dependency Patterns
// Run once on mount
useEffect(() => {
console.log('Component mounted');
}, []);
// Run on every render
useEffect(() => {
console.log('Component rendered');
});
// Run when specific values change
useEffect(() => {
console.log('Count changed');
}, [count]);
// Run when any of multiple values change
useEffect(() => {
console.log('Count or name changed');
}, [count, name]);
Event Handling
React events are named using camelCase and pass functions as event handlers.
Button Click Events
function ButtonExample() {
const handleClick = () => {
alert('Button clicked!');
};
// Inline function
const handleClickInline = () => {
console.log('Inline click');
};
return (
<div>
<button onClick={handleClick}>Click Me</button>
<button onClick={handleClickInline}>Inline Handler</button>
<button onClick={() => alert('Direct inline')}>Direct</button>
</div>
);
}
Form Events
function LoginForm() {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const handleSubmit = (e) => {
e.preventDefault(); // Prevent page reload
console.log('Form submitted:', formData);
// Send data to server
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}
Mouse Events
function MouseExample() {
const [position, setPosition] = useState({ x: 0, y: 0 });
return (
<div
onMouseMove={(e) => setPosition({ x: e.clientX, y: e.clientY })}
onMouseEnter={() => console.log('Mouse entered')}
onMouseLeave={() => console.log('Mouse left')}
style={{ height: '200px', border: '1px solid black' }}
>
<p>X: {position.x}, Y: {position.y}</p>
</div>
);
}
Conditional Rendering
If-Else with Variables
function Greeting({ isLoggedIn }) {
let content;
if (isLoggedIn) {
content = <h1>Welcome back!</h1>;
} else {
content = <h1>Please sign in</h1>;
}
return <div>{content}</div>;
}
Ternary Operator
function LoginStatus({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
);
}
Logical && Operator
function Mailbox({ unreadMessages }) {
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && (
<h2>You have {unreadMessages.length} unread messages.</h2>
)}
</div>
);
}
Switch Statement Pattern
function StatusBadge({ status }) {
const renderBadge = () => {
switch (status) {
case 'success':
return <span className="badge-success">ā Success</span>;
case 'error':
return <span className="badge-error">ā Error</span>;
case 'warning':
return <span className="badge-warning">ā Warning</span>;
default:
return <span className="badge-info">ā¹ Info</span>;
}
};
return <div>{renderBadge()}</div>;
}
Lists and Keys
Rendering Lists
function TodoList() {
const todos = [
{ id: 1, text: 'Learn React', completed: false },
{ id: 2, text: 'Build a project', completed: false },
{ id: 3, text: 'Deploy to production', completed: true }
];
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
{todo.completed && ' ā'}
</li>
))}
</ul>
);
}
Keys Explained
Keys help React identify which items have changed, are added, or removed:
// ā
Good - using unique ID
{items.map(item => <li key={item.id}>{item.name}</li>)}
// ā ļø OK - using index (only if list never changes)
{items.map((item, index) => <li key={index}>{item.name}</li>)}
// ā Bad - no key
{items.map(item => <li>{item.name}</li>)}
Complex List Example
function ProductList({ products }) {
return (
<div className="product-grid">
{products.map(product => (
<div key={product.id} className="product-card">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>${product.price}</p>
<button>Add to Cart</button>
</div>
))}
</div>
);
}
Real-World Example
Let's build a complete Todo App combining everything we've learned:
import { useState, useEffect } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const [filter, setFilter] = useState('all'); // all, active, completed
// Load todos from localStorage
useEffect(() => {
const saved = localStorage.getItem('todos');
if (saved) {
setTodos(JSON.parse(saved));
}
}, []);
// Save todos to localStorage
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
const addTodo = (e) => {
e.preventDefault();
if (input.trim()) {
setTodos([
...todos,
{
id: Date.now(),
text: input,
completed: false,
createdAt: new Date().toISOString()
}
]);
setInput('');
}
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const filteredTodos = todos.filter(todo => {
if (filter === 'active') return !todo.completed;
if (filter === 'completed') return todo.completed;
return true;
});
return (
<div className="todo-app">
<h1>My 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')}>All</button>
<button onClick={() => setFilter('active')}>Active</button>
<button onClick={() => setFilter('completed')}>Completed</button>
</div>
{/* Todo List */}
<ul className="todo-list">
{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>
{/* Stats */}
<div className="stats">
<p>{filteredTodos.length} items</p>
<p>{todos.filter(t => !t.completed).length} active</p>
</div>
</div>
);
}
export default TodoApp;
Next Steps
Congratulations! You've learned the fundamentals of React. Here's what to learn next:
Intermediate Topics
- React Router: Navigation and routing
- Context API: Advanced state management
- Custom Hooks: Reusable logic
- useReducer: Complex state logic
- Performance Optimization: memo, useMemo, useCallback
Advanced Topics
- TypeScript with React: Type-safe React apps
- Testing: Jest and React Testing Library
- State Management: Redux, Zustand, Recoil
- Server-Side Rendering: Next.js
- React Native: Mobile app development
Practice Projects
- Weather App with API
- E-commerce Product Page
- Social Media Dashboard
- Blog with Authentication
- Real-time Chat Application
Common Mistakes to Avoid
1. Mutating State Directly
// ā Wrong
state.count = state.count + 1;
// ā
Correct
setState({ ...state, count: state.count + 1 });
2. Missing Keys in Lists
// ā Wrong
items.map(item => <li>{item}</li>)
// ā
Correct
items.map((item, id) => <li key={id}>{item}</li>)
3. Forgetting to Prevent Default
// ā Wrong - page reloads
<form onSubmit={handleSubmit}>
// ā
Correct
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
4. Comparing Objects in useEffect
// ā Wrong - runs every render
useEffect(() => {}, [objectProp]);
// ā
Correct - compare specific properties
useEffect(() => {}, [objectProp.id, objectProp.name]);
Best Practices
- Keep Components Small: One component, one responsibility
- Use Functional Components: Prefer hooks over class components
- Meaningful Names: Use descriptive names for components and functions
- DRY Principle: Don't repeat yourself - create reusable components
- PropTypes or TypeScript: Add type checking
- Folder Structure: Organize components logically
- Comments: Document complex logic
- Error Boundaries: Handle errors gracefully
Resources
- Official Docs: https://react.dev
- React DevTools: Browser extension for debugging
- Create React App: https://create-react-app.dev
- Awesome React: Community-curated list of resources
- React Patterns: Common design patterns
Conclusion
You now have a solid foundation in React! Remember:
- Practice regularly: Build small projects
- Read documentation: React docs are excellent
- Join communities: Reddit, Discord, Stack Overflow
- Stay updated: React evolves constantly
- Contribute: Open source projects welcome beginners
Happy coding! š