Introduction to Hooks
Understand the fundamentals of React Hooks and why they were introduced
50 min•By Priygop Team•Last updated: Feb 2026
What are React Hooks?
React Hooks are functions that allow you to use state and other React features in function components. They were introduced in React 16.8 to allow you to use state and other React features without writing a class.
Why Hooks?
- Use state and other React features without classes
- Reuse stateful logic between components
- Split one component into smaller functions
- Avoid complex patterns like render props and HOCs
Rules of Hooks
- Only call hooks at the top level of your function
- Don't call hooks inside loops, conditions, or nested functions
- Only call hooks from React function components or custom hooks
- Hooks must be called in the same order every time
Basic Hook Example
Example
import React, { useState } from 'react';
function Example() {
// Declare a new state variable called "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
// Before Hooks (Class Component)
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}Hooks vs Class Components
Example
// Class Component with multiple state
class UserProfile extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
age: 0,
isEditing: false
};
}
handleNameChange = (e) => {
this.setState({ name: e.target.value });
};
handleEmailChange = (e) => {
this.setState({ email: e.target.value });
};
toggleEditing = () => {
this.setState(prevState => ({
isEditing: !prevState.isEditing
}));
};
render() {
return (
<div>
{this.state.isEditing ? (
<div>
<input
value={this.state.name}
onChange={this.handleNameChange}
/>
<input
value={this.state.email}
onChange={this.handleEmailChange}
/>
<button onClick={this.toggleEditing}>Save</button>
</div>
) : (
<div>
<h2>{this.state.name}</h2>
<p>{this.state.email}</p>
<button onClick={this.toggleEditing}>Edit</button>
</div>
)}
</div>
);
}
}
// Function Component with Hooks (equivalent)
function UserProfile() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
const [isEditing, setIsEditing] = useState(false);
const toggleEditing = () => {
setIsEditing(!isEditing);
};
return (
<div>
{isEditing ? (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button onClick={toggleEditing}>Save</button>
</div>
) : (
<div>
<h2>{name}</h2>
<p>{email}</p>
<button onClick={toggleEditing}>Edit</button>
</div>
)}
</div>
);
}
// Advantages of Hooks:
// - Less code and boilerplate
// - Easier to understand and test
// - Better performance optimization
// - Reusable logic between componentsPractice Exercise: Converting Class to Hooks
Example
// Exercise: Convert a Class Component to Function Component with Hooks
// Convert this class component to use hooks
// Original Class Component
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [],
inputValue: '',
filter: 'all'
};
}
componentDidMount() {
// Load todos from localStorage
const savedTodos = localStorage.getItem('todos');
if (savedTodos) {
this.setState({ todos: JSON.parse(savedTodos) });
}
}
componentDidUpdate(prevProps, prevState) {
// Save todos to localStorage when they change
if (prevState.todos !== this.state.todos) {
localStorage.setItem('todos', JSON.stringify(this.state.todos));
}
}
addTodo = () => {
if (this.state.inputValue.trim()) {
this.setState(prevState => ({
todos: [...prevState.todos, {
id: Date.now(),
text: prevState.inputValue,
completed: false
}],
inputValue: ''
}));
}
};
toggleTodo = (id) => {
this.setState(prevState => ({
todos: prevState.todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
)
}));
};
deleteTodo = (id) => {
this.setState(prevState => ({
todos: prevState.todos.filter(todo => todo.id !== id)
}));
};
setFilter = (filter) => {
this.setState({ filter });
};
render() {
const filteredTodos = this.state.todos.filter(todo => {
if (this.state.filter === 'active') return !todo.completed;
if (this.state.filter === 'completed') return todo.completed;
return true;
});
return (
<div>
<input
value={this.state.inputValue}
onChange={(e) => this.setState({ inputValue: e.target.value })}
placeholder="Add todo"
/>
<button onClick={this.addTodo}>Add</button>
<div>
<button onClick={() => this.setFilter('all')}>All</button>
<button onClick={() => this.setFilter('active')}>Active</button>
<button onClick={() => this.setFilter('completed')}>Completed</button>
</div>
<ul>
{filteredTodos.map(todo => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => this.toggleTodo(todo.id)}
/>
<span style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}>
{todo.text}
</span>
<button onClick={() => this.deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
}
// Your Task: Convert the above class component to a function component using hooks
// Use useState for state management
// Use useEffect for side effects (localStorage)
// Maintain the same functionality
// Hint: You'll need:
// - useState for todos, inputValue, and filter
// - useEffect for localStorage operations
// - Event handlers as regular functions
// Challenge: Add a custom hook for localStorage management
// Challenge: Add a custom hook for todo filtering
// Challenge: Add a custom hook for todo operationsTry It Yourself — Introduction to Hooks
Try It Yourself — Introduction to HooksHTML
HTML Editor
✓ ValidTab = 2 spaces
HTML|30 lines|1048 chars|✓ Valid syntax
UTF-8