Beginner's Guide to React Hooks: Understanding the Basics
React Hooks, introduced in React 16.8, enable state and lifecycle features in functional components without using classes. This article covers the basics of useState and useEffect with practical examples, including state management, handling side effects, and creating custom hooks for reusable logic.
Introduction 🔌
React Hooks, introduced in React 16.8, have revolutionized how developers build components. They allow you to use state and other React features without writing a class. In this article, we will explore the basics of React Hooks, focusing on useState
and useEffect
, and provide practical examples to help you get started.
What Are Hooks? 🎣
Hooks are functions that let you “hook into” React state and lifecycle features from function components. They make it possible to organize the logic inside a component into reusable isolated units.
useState: State in Functional Components
The useState
hook allows you to add state to your functional components. Here's how it works:
import React, { 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>
);
}
export default Counter;
In this example, useState(0)
initializes the state variable count
with a value of 0. The setCount
function updates the state.
useEffect: Handling Side Effects
The useEffect
hook lets you perform side effects in function components. It’s similar to lifecycle methods like componentDidMount
, componentDidUpdate
, and componentWillUnmount
in class components.
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(seconds => seconds + 1);
}, 1000);
return () => clearInterval(interval); // Cleanup on unmount
}, []); // Empty array means this effect runs only once after the initial render
return (
<div>
<p>{seconds} seconds have elapsed since mounting.</p>
</div>
);
}
export default Timer;
Here, useEffect
sets up a timer that increments the seconds
state every second. The cleanup function, clearInterval
, prevents memory leaks by stopping the timer when the component unmounts.
Combining useState and useEffect 🫱🏻🫲🏾
Often, you'll need to use multiple hooks together. For example, fetching data when a component mounts:
import React, { useState, useEffect } from 'react';
function FetchData() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, []); // Empty array ensures this effect runs only once
if (loading) {
return <p>Loading...</p>;
}
return (
<div>
<h1>Fetched Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default FetchData;
This component fetches data from an API and updates the state with the response. The loading state ensures a loading message is shown until the data is fetched.
Custom Hooks: Reusable Logic 🔄️
You can create your own hooks to reuse stateful logic across components. For example, a custom hook for fetching data:
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, [url]); // Re-run effect if URL changes
return { data, loading };
}
export default useFetch;
You can use this custom hook in any component:
import React from 'react';
import useFetch from './useFetch';
function DataDisplay({ url }) {
const { data, loading } = useFetch(url);
if (loading) {
return <p>Loading...</p>;
}
return (
<div>
<h1>Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default DataDisplay;
Conclusion ✅
React Hooks provide a powerful way to use state and other React features in functional components. useState
and useEffect
are just the beginning—there are many other hooks and patterns you can explore to make your components more modular and maintainable. Keep experimenting and happy coding!
Subscribe to my newsletter
Read articles from Hugo Tavares directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Hugo Tavares
Hugo Tavares
Hello World, my name is Hugo. I’m a Christian, husband, and father. I hold a degree in Administration and have experience in the military as an air traffic controller. Additionally, I’m a frontend developer, fascinated by technology, and constantly seeking to learn new things.