Beginner-friendly guide to fetching JSON from JSONPlaceholder using fetch in a Vite + React app. Build loading and error states and render a posts list. Includes a handoff to Part 2 (Axios + custom hook).
React API Series: Part 1 - Fetching Data with Fetch
In modern web development, interacting with APIs is a crucial skill. APIs (Application Programming Interfaces) allow us to retrieve data from servers, enabling dynamic web applications. In this first part of our three-part series, we'll set up a basic application using React and the Vite build tool, fetching posts from the JSONPlaceholder API.
Glossary
- API: A set of rules that allows one piece of software to interact with another.
- Endpoint: A URL where an API can be accessed by a client to perform operations (like fetching data).
- JSON: JavaScript Object Notation; a lightweight format for data interchange that is easy to read and write.
Project Setup
Create a new Vite project by running the commands:
npm create vite@latest react-api-series --template react cd react-api-series npm installRun the development server:
npm run devThe server should now be running at
http://localhost:5173.
Create src/api/client.js
First, let’s create a separate file to handle our API client. This will allow us to fetch posts using the Fetch API.
Creating client.js
// src/api/client.js
export async function getPosts() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching posts:', error);
throw error;
}
}What this code does
- Defines an asynchronous function
getPoststo fetch data from the specified endpoint. - Checks for network errors by examining the response status using
response.ok. - Parses the response to JSON if the fetch was successful.
- Catches and logs errors that may occur during the fetch operation, rethrowing them for upstream handling.
Create src/App.jsx
Next, let’s modify our main application component to utilize the getPosts function and display the list of posts.
Modifying App.jsx
// src/App.jsx
import React, { useEffect, useState } from 'react';
import { getPosts } from './api/client';
function App() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
const postsData = await getPosts();
setPosts(postsData);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchData();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h1>Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default App;What this code does
- Defines an
Appfunctional component, managing three states:posts,loading, anderror. - Uses the
useEffecthook to fetch posts once the component mounts. - Handles data fetching with an asynchronous function
fetchData, updating state based on the fetch outcome. - Renders a loading message while loading, an error message if an error occurs, or the list of post titles if successful.
Recap
In part one, we spun up a Vite-powered React app, built a lightweight API client to pull posts from JSONPlaceholder, and handled loading and error states for a smooth, resilient UI.
Browse the code on GitHub: github repository
Part 2
In the next part, we will enhance our data fetching by implementing Axios and custom hooks for improved data management and reusability.