0% completed
In modern web development, fetching data is an essential task. It’s how applications get information from a source within an application. Data fetching is vital for creating interactive, data-driven applications, allowing them to deliver dynamic content tailored to user needs. In React, the useEffect
hook is your go-to tool for data fetching.
Data fetching typically involves retrieving data from an external source such as a server, database, API, or internal JSON file, so your application can use it. For example:
However, fetching data in React is different from the way you fetch in JavaScript. Lets look at a Fetch function that fetches data from an API in a functional component.
function App() { const [posts, setPosts] = useState([]) fetch('https://jsonplaceholder.typicode.com/posts') .then(res=>res.json()) .then(data=>setPosts(data)) return ( <> <h1 className='bg-blue-500'>Data fetching using fetch</h1> <ul> {posts.map(post => ( <li key={post.id}>{post.title}</li> ))} </ul> </> ) } export default App
In this code example:
useState
hook is declared with a state
of posts, updater function of setPosts
and the initial state set to empty array ([]).setPosts
updater function updates the posts state with the fetched data.This looks like a successful fetch process because the post titles are displayed on the webpage.
However, a look at the Network tab of the browser shows a big problem with the fetch process. The problem is that the fetch call is directly inside the component body, which means it will run on every re-render, causing an infinite loop of requests.
In this image, you can see that there is an infinite loop of requests causing excessive re-renders (776 requests in just under 3 secs). While the data is displayed on the webpage, the frequent GET requests been made under the hood causes performance issues and excessive load on the server. This is the issue that the useEffect solves.
React’s useEffect
hook is designed to handle side effects—things that happen outside the normal rendering of your component. Fetching data is a classic example of a side effect.
Here’s the basic structure of the useEffect
hook:
useEffect(() => { // Code to run after the component is rendered }, [dependencies]);
For data fetching, you’ll usually run the useEffect
hook when the component first appears, which means the dependency array will be empty ([]
).
The dependency array is a crucial part of the useEffect
hook. It controls how often the effect runs. Let’s break it down:
Empty Array ([]
)
The effect runs only once when the component mounts (initially renders). This is perfect for fetching data.
useEffect(() => { console.log("This runs once!"); }, []);
With Dependencies
The effect runs every time a dependency changes.
useEffect(() => { console.log("This runs whenever `count` changes."); }, [count]);
No Array
If you omit the array, the effect runs after every render, which can lead to performance issues.
useEffect(() => { console.log("This runs after every render!"); });
For data fetching, you’ll typically use an empty array to ensure the fetch happens only once.
.....
.....
.....