Let's compare a REST API and a GraphQL API using a practical example and demonstrate how they differ when fetching data from a frontend client, such as React.
Scenario: Consider a simple application for a library that stores information about books and authors.
REST API Example:
Server (Node.js with Express):
Assuming you have a RESTful API for books and authors:
const express = require('express');
const app = express();
// Define routes for books and authors
app.get('/api/books', (req, res) => {
// Logic to fetch a list of books from a database
const books = /* ... */;
res.json(books);
});
app.get('/api/authors', (req, res) => {
// Logic to fetch a list of authors from a database
const authors = /* ... */;
res.json(authors);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Frontend (React):
In a React component, you would make separate HTTP requests to fetch books and authors:
import React, { useEffect, useState } from 'react';
function App() {
const [books, setBooks] = useState([]);
const [authors, setAuthors] = useState([]);
useEffect(() => {
// Fetch books
fetch('/api/books')
.then((response) => response.json())
.then((data) => setBooks(data));
// Fetch authors
fetch('/api/authors')
.then((response) => response.json())
.then((data) => setAuthors(data));
}, []);
return (
<div>
<h1>Library App</h1>
<h2>Books</h2>
<ul>
{books.map((book) => (
<li key={book.id}>{book.title}</li>
))}
</ul>
<h2>Authors</h2>
<ul>
{authors.map((author) => (
<li key={author.id}>{author.name}</li>
))}
</ul>
</div>
);
}
export default App;
In this REST API example, you have separate endpoints for books and authors. You make two separate requests from the frontend, one for books and one for authors.
GraphQL API Example:
Server (Node.js with Express and Apollo Server):
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const app = express();
// Define GraphQL schema
const typeDefs = gql`
type Book {
id: ID
title: String
}
type Author {
id: ID
name: String
}
type Query {
books: [Book]
authors: [Author]
}
`;
// Define resolvers
const resolvers = {
Query: {
books: () => {
// Logic to fetch a list of books from a database
const books = /* ... */;
return books;
},
authors: () => {
// Logic to fetch a list of authors from a database
const authors = /* ... */;
return authors;
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.applyMiddleware({ app });
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Frontend (React with Apollo Client):
In a React component, you would use Apollo Client to fetch data via a single GraphQL query:
import React from 'react';
import { ApolloClient, InMemoryCache, ApolloProvider, useQuery, gql } from '@apollo/client';
const client = new ApolloClient({
uri: '/graphql', // GraphQL endpoint
cache: new InMemoryCache(),
});
const GET_BOOKS_AND_AUTHORS = gql`
query {
books {
id
title
}
authors {
id
name
}
}
`;
function App() {
const { loading, error, data } = useQuery(GET_BOOKS_AND_AUTHORS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
const { books, authors } = data;
return (
<div>
<h1>Library App</h1>
<h2>Books</h2>
<ul>
{books.map((book) => (
<li key={book.id}>{book.title}</li>
))}
</ul>
<h2>Authors</h2>
<ul>
{authors.map((author) => (
<li key={author.id}>{author.name}</li>
))}
</ul>
</div>
);
}
export default function ApolloApp() {
return (
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
}
In this GraphQL API example, you have a single GraphQL endpoint. The frontend sends a single GraphQL query **(GET_BOOKS_AND_AUTHORS) **to request both books and authors data in one request.
Key Differences:
Endpoint: REST typically has multiple endpoints for different resources, while GraphQL has a single endpoint for all queries and mutations.
Over-fetching and Under-fetching: In REST, you might over-fetch data (get more than needed) or under-fetch data (get less than needed). In GraphQL, the client specifies exactly what data it needs, avoiding over-fetching or under-fetching.
Multiple Requests vs. Single Request: In REST, you often make multiple requests to different endpoints. In GraphQL, you make a single request with multiple queries to fetch related data.
Versioning: REST APIs often require versioning to handle changes. GraphQL allows clients to request only the fields they need, reducing the need for versioning.
GraphQL offers more flexibility and efficiency by allowing clients to request precisely the data they require in a single query, reducing over-fetching and under-fetching, and eliminating the need for multiple endpoints or versioning.
Top comments (0)