Article

React Hooks: A Beginner’s Guide to Modern React

5 min read
Originally published on Medium. Read, clap or comment on Medium ↗

Unlock the power of functional components and write cleaner, more intuitive React code


If you’re diving into React development in 2025, you’ve probably heard the term “Hooks” thrown around quite a bit. Maybe you’ve seen code snippets with useState and useEffect and wondered what magic is happening behind those simple-looking functions. Don't worry—you're in the right place.

React Hooks revolutionized how we write React applications, making code more readable, reusable, and just plain fun to work with. In this guide, we’ll demystify Hooks and get you comfortable using them in your own projects.

What Are React Hooks, Anyway?

Before Hooks came along in React 16.8 (February 2019), if you needed to manage state or tap into lifecycle methods, you had to use class components. This meant writing more boilerplate code, dealing with the confusing this keyword, and struggling to reuse stateful logic between components.

Hooks changed everything. They’re special functions that let you “hook into” React features like state and lifecycle methods directly from functional components. No classes required.

Think of Hooks as your toolkit for building powerful components with less code and more clarity.

The Essential Hooks You Need to Know

1. useState: Managing Component State

useState is your go-to Hook for adding state to functional components. It's beautifully simple.

import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

Here’s what’s happening:

Every time you call setCount, React re-renders your component with the new state value. Simple, elegant, powerful.

2. useEffect: Side Effects Made Easy

useEffect is where you handle side effects—things like fetching data, subscribing to services, or manually manipulating the DOM. Think of it as componentDidMount, componentDidUpdate, and componentWillUnmount combined into one API.

import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true); useEffect(() => {
// This runs after every render by default
async function fetchUser() {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
} fetchUser();
}, [userId]); // Only re-run when userId changes if (loading) return <div>Loading...</div>;
return <div>Welcome, {user.name}!</div>;
}

The second argument to useEffect is the dependency array. It tells React when to re-run your effect:

3. useContext: Sharing Data Without Props Drilling

Passing props down through multiple levels of components gets messy fast. useContext lets you share data across your component tree without the hassle.

import { createContext, useContext, useState } from 'react';
// Create a context
const ThemeContext = createContext();function App() {
const [theme, setTheme] = useState('light'); return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
}function Toolbar() {
return <ThemeButton />;
}function ThemeButton() {
// Access context directly, no props needed!
const { theme, setTheme } = useContext(ThemeContext); return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}

No more passing theme through every intermediate component. Beautiful.

The Rules of Hooks (Yes, There Are Rules)

Hooks are powerful, but they come with two important rules:

1. Only call Hooks at the top level Don’t call Hooks inside loops, conditions, or nested functions. React relies on the order Hooks are called to track state correctly.

// ❌ Bad
function BadComponent() {
if (someCondition) {
const [state, setState] = useState(0); // Don't do this!
}
}
// ✅ Good
function GoodComponent() {
const [state, setState] = useState(0);

if (someCondition) {
// Use the state here instead
}
}

2. Only call Hooks from React functions Call Hooks from React functional components or custom Hooks — not from regular JavaScript functions.

Building Your Own Custom Hooks

Here’s where Hooks really shine: you can create your own! Custom Hooks let you extract component logic into reusable functions.

import { useState, useEffect } from 'react';
// Custom Hook for fetching data
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null); useEffect(() => {
async function fetchData() {
try {
setLoading(true);
const response = await fetch(url);
const json = await response.json();
setData(json);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
} fetchData();
}, [url]); return { data, loading, error };
}// Now use it anywhere!
function UserList() {
const { data: users, loading, error } = useFetch('/api/users'); if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>; return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}

Custom Hooks must start with “use” so React can recognize them and apply Hook rules. They’re just functions that can use other Hooks inside them.

More Hooks to Explore

Once you’re comfortable with the basics, check out these additional Hooks:

Why Hooks Matter

Hooks aren’t just a new syntax — they represent a fundamental shift in how we think about React components. They encourage:

The React team designed Hooks to be gradually adoptable. You don’t need to rewrite your existing class components — Hooks work alongside them perfectly. But for new code, Hooks offer a more intuitive and maintainable approach.

Your Next Steps

Start small. Pick a simple component in your project and convert it to use Hooks. Practice with useState and useEffect until they feel natural. Then experiment with creating your own custom Hooks.

The React documentation has excellent resources for diving deeper, and the community has built thousands of custom Hooks for common use cases — from form handling to animations to API integrations.

Welcome to the world of Hooks. Your React code is about to get a whole lot cleaner.


Ready to start building? Grab the official React docs and start hooking up your components. Happy coding!

← All articles Discuss on Medium ↗