[Ctrl J]
[Ctrl K]
light/dark
How many ways can we fetch the Pokemon API with either Server or Client components? Personally, I know at least three ways: fetching data from the server with the fetch API, fetching data from the client with the fetch API, and fetching data from the client with a third-party library like useSWR
. In this blog, we'll demonstrate how to fetch data based on a single user input using all three methods mentioned above.
Getting Started
Create a Next.js project. In an earlier blog, I implemented a Search
component utilizing URL search params. We will use this component to get input from the user. The user - you - will type in a number so that we can construct a string containing the URL to the Pokemon API like this: https://pokeapi.co/api/v2/pokemon/${input}
. Let's create a page.tsx
file in the app/pokemon
directory, along with three components (ServerFetch
, ClientFetch
, and ClientSWR
) in the components
folder. We'll implement a unique data fetching method in each component.
// src/app/pokemon/page.tsximport Search from "../components/Search";import ServerFetch from "../components/ServerFetch";import ClientFetch from "../components/ClientFetch";import ClientSWR from "../components/ClientSWR";const page = () => {return (<div><Search /><ServerFetch /><ClientFetch /><ClientSWR /></div>);};export default page;
Modify page.tsx
and each of the three components so that we can pass the search query down to the components.
// src/app/ServerFetch.tsx// ...type PageProps = {searchParams: {query?: string;};};const Page = ({ searchParams }: PageProps) => {const id = searchParams.query || "1";return (<div><Search /><ServerFetch id={id} /><ClientFetch id={id} /><ClientSWR id={id} /></div>);};export default Page;
// src/app/components/ServerFetch.tsxtype ServerFetchProps = {id: string;};const ServerFetch = ({ id }: ServerFetchProps) => {return <div>{id}</div>;};export default ServerFetch;
Fetching data from the server with fetch API
Here's the gist of fetching data on the server with fetch API:
await fetch()
inside the component to make the API call.await response.json()
).This approach allows you to fetch and use data directly within server components, simplifying the process compared to older Next.js data fetching methods. Here's the code in action:
// src/app/components/ServerFetch.tsxtype ServerFetchProps = {id: string;};const ServerFetch = async ({ id }: ServerFetchProps) => {const fetchPokemon = async (id: string) => {const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);const data = res.json();return data;};const pokemon = await fetchPokemon(id);return <div>{pokemon.name}</div>;};export default ServerFetch;
Fetching data on the client with fetch API
We fetch data with the Fetch API on a client component using useState
and useEffect
:
This is the basic implementation:
"use client";import { useEffect, useState } from "react";type ClientFetchProps = {id: string;};interface Pokemon {name: string;}const ClientFetch = ({ id }: ClientFetchProps) => {const [pokemon, setPokemon] = useState<Pokemon | null>(null);useEffect(() => {const fetchPokemon = async (id: string) => {const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);const data = await res.json();setPokemon(data);};fetchPokemon(id);}, [id]);return <div>{pokemon?.name}</div>;};export default ClientFetch;
Remember to use "use client"
directive to create a client component in Next.js.
Fetching data on the client with third party library
We use useSWR
to demonstrate fetching data with a third party library. Here's the gist of it:
useSWR
from the swr
packageuseSWR
hook in your component"use client";import React from "react";import useSWR from "swr";type ClientSWRProps = {id: string;};interface Pokemon {name: string;}const fetcher = async (url: string): Promise<Pokemon> => {const res = await fetch(url);const data = await res.json();return data;};const ClientSWR = ({ id }: ClientSWRProps) => {const {data: pokemon,error,isLoading,} = useSWR(`https://pokeapi.co/api/v2/pokemon/${id}`, fetcher);if (error) return <div>Error</div>;if (isLoading) return <div>Loading...</div>;return <div>{pokemon?.name}</div>;};export default ClientSWR;
Summary
Ultimately, the best approach for fetching data in your application depends on your specific requirements, SEO, and the complexity of your data fetching needs. By understanding the strengths and weaknesses of each method, you can make informed decisions about how to fetch data in your projects.