Fetching Data
So you want to grab some data from an API? React makes this straightforward once you understand the pattern. Think of fetching data like ordering food delivery — you place the order, wait for it, and then enjoy your meal.
The key is using the useEffect hook combined with the fetch API. This combo lets you reach out to servers and bring back whatever goodies you need.
Basic Fetch Pattern
Here is the simplest way to fetch data when your component loads. We use useEffect to trigger the fetch on mount, then store the result in state.
import { useState, useEffect } from 'react'
function UserProfile() {
const [user, setUser] = useState(null)
useEffect(() => {
fetch('https://api.example.com/user/1')
.then(response => response.json())
.then(data => setUser(data))
}, [])
if (!user) return Loading...
return {user.name}
}
The empty dependency array tells React to run this only once when the component first appears. Without it, you would be fetching data in an endless loop.
Async Await Approach
Some developers prefer async/await because it reads more like regular English. Same concept, just different syntax. Pick whichever feels more natural to you.
import { useState, useEffect } from 'react'
function ProductList() {
const [products, setProducts] = useState([])
useEffect(() => {
const getProducts = async () => {
const response = await fetch('https://api.example.com/products')
const data = await response.json()
setProducts(data)
}
getProducts()
}, [])
return (
{products.map(p => (
- {p.name}
))}
)
}
Notice we create an async function inside useEffect and then call it. This keeps things clean and readable.
Handling Responses
Real APIs do not always cooperate. Sometimes you get errors, sometimes the data looks different than expected. Always add error handling to keep your app from crashing.
import { useState, useEffect } from 'react'
function WeatherWidget() {
const [weather, setWeather] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
const fetchWeather = async () => {
try {
const res = await fetch('https://api.example.com/weather')
if (!res.ok) throw new Error('Failed to fetch')
const data = await res.json()
setWeather(data)
} catch (err) {
setError(err.message)
}
}
fetchWeather()
}, [])
if (error) return Something went wrong: {error}
if (!weather) return Loading weather...
return Temperature: {weather.temp}°C
}
The try/catch block catches network errors, and checking res.ok handles server-side errors. This pattern covers most real-world scenarios.
Try it Yourself →