Skip to main content
Course/Module 2/Topic 1 of 4Beginner

Introduction to Hooks

Understand the fundamentals of React Hooks and why they were introduced

50 minBy Priygop TeamLast 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 components

Practice 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 operations

Try 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

📚 Additional Resources

Recommended Reading

  • React Hooks Documentation
  • React Hooks in Action by Mark Tielens Thomas
  • Custom Hooks Best Practices

Online Resources

  • React Hooks Tutorial
  • useEffect Complete Guide
  • Custom Hooks Examples
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep