Next.js propose plusieurs méthodes pour récupérer les données, car il prend en charge le rendu côté client et côté serveur. La première consiste à utiliser SWR, qui est un ensemble de hooks React pour la récupération de données à distance.
Dans ce tutoriel, nous examinerons SWR, une bibliothèque qui facilite la mise en cache, la pagination, la revalidation, etc. Nous allons également créer une application Next (côté client) qui récupère les données depuis JSON Placeholder à l'aide de SWR.
Sorry for the interrupt!
If you're interested in learning React, or Next.js in a comprehensive way, I highly recommend these bestseller courses:
> Complete Next.js with React & Node - Beautiful Portfolio App
> React - The Complete Guide (incl Hooks, React Router, Redux)
- Qu'est-ce que SWR?
- Configuration
- Récupération des données avec ʻuseSWR`
- Création des composants
- Pagination des données avec
useSWRInfinite
Commençons!
Qu'est-ce que SWR?
SWR signifie stale-while-revalidate
. C'est une bibliothèque légère créée par la même équipe derrière Next.js. Il permet de récupérer, de mettre en cache ou de faire une nouvelle requête de données en temps réel avec React Hooks. SWR procède en trois étapes: d'abord, il retourne le cache (passé), puis récupère les données du serveur (revalidation), et enfin vient avec les données à jour. De cette façon, SWR améliore votre expérience utilisateur en vous permettant de montrer quelque chose à votre utilisateur tout en récupérant les nouvelles données du serveur.
SWR est indépendant du backend, ce qui signifie que vous pouvez l'utiliser pour récupérer des données depuis n'importe quel serveur prenant en charge les requêtes HTTP. Il a également un bon support pour TypeScript et le rendu côté serveur. Contrairement à React, Next.js est livré avec SWR.
Cela dit, nous pouvons mettre la main à la pâte et configurer une nouvelle application Next.js pour utiliser les fonctionnalités SWR.
Configuration
Pour configurer une nouvelle application, nous allons utiliser Create Next App. Commencez par ouvrir votre interface de ligne de commande (CLI) et exécutez cette commande:
npx create-next-app next-swr-app
Ensuite, structurez le dossier comme ceci:
├── components
| └── Post.js
├── pages
| └── index.js
├── useRequest.js
└── package.json
Décomposons la structure du fichier:
Post.js
est le composant responsable de l'affichage de l'objet depost
.index.js
est la page d'accueil de notre application.useRequest.js
est un hook personnalisé qui aide à récupérer les données en utilisant SWR.
Avec cette structure de dossiers en place, nous pouvons commencer à récupérer les données distantes à partir de JSON Placeholder dans la section suivante.
Récupération des données avec ʻuseSWR`
Pour récupérer des données distantes avec SWR, nous pouvons utiliser soit useSWR
, soit useSWRInfinite
. Cependant, il existe certaines différences entre les crochets. Le premier est utilisé uniquement pour la récupération de données, tandis que le second hook permet de récupérer et de paginer les données. Vous pouvez utiliser useSWRInfinite
pour ajouter un défilement infinie ou une pagination dans votre application Next.js en un rien de temps.
Maintenant, explorons le fichier useRequest.js
:
import useSWR from "swr"
const fetcher = url => fetch(url).then(res => res.json())
const baseUrl = "https://jsonplaceholder.typicode.com"
export const useGetPosts = path => {
if (!path) {
throw new Error("Path is required")
}
const url = baseUrl + path
const { data: posts, error } = useSWR(url, fetcher)
return { posts, error }
}
L'utilisation de ce hook personnalisé pour récupérer des données est facultative. Vous pouvez également utiliser les crochets SWR directement dans vos composants.
La fonction fetcher
nous permet d'envoyer la requête HTTP au serveur, puis de transformer les données de réponse en JSON. La méthode fetch
provient du paquet unfetch
fourni avec Next.js.
Ensuite, nous utilisons la fonction useGetPosts
pour envoyer la requête avec le hook useSWR
. Il s'attend à recevoir comme arguments l'URL du serveur et une fonction fetcher
pour exécuter la requête. Une fois les données récupérées, nous retournons les posts
récupérés et un état error
.
Avec ce hook personnalisé prêt à l'emploi, nous pouvons désormais créer les composants pour afficher les messages récupérés.
Création des composants
composants / Post.js
export default function Post({ post }) {
const { title, body, id } = post
return (
<div className="Card">
<h1 className="Card--title">
{id}. {title}
</h1>
<p className="Card--body">{body}</p>
</div>
)
}
Comme vous pouvez le voir, nous avons un composant simple qui reçoit le post
à afficher en tant que paramètre. Ensuite, nous utilisons la déstructuration pour extraire les éléments de l'objet afin d'afficher le post.
App.js
import { useGetPosts } from "../useRequest"
import Post from "../components/Post"
export default function IndexPage() {
const { posts, error } = useGetPosts("/posts")
if (error) return <h1>Something went wrong!</h1>
if (!posts) return <h1>Loading...</h1>
return (
<div className="container">
<h1>My Posts</h1>
{posts.map(post => (
<Post post={post} key={post.id} />
))}
</div>
)
}
Ici, nous commençons par importer le hook useGetPosts
, puis nous passons le chemin comme argument pour exécuter la requête. Il renvoie les posts
à afficher et un état d'erreur.
Après cela, nous utilisons le composant Post
pour afficher le tableau de données. Si une erreur se produit, nous la traitons en conséquence avec l'etat error
fournie par SWR.
Avec cette avancée, nous pouvons vérifier si tout fonctionne dans le navigateur. Pour ce faire, ouvrez le projet sur la CLI et exécutez la commande suivante:
yarn dev
Ou pour npm
npm run dev
Visitez sur le navigateur http://localhost:3000
Génial! Nos données sont récupérées avec succès depuis le serveur en utilisant le hook useSWR
.
Comme nous l'avons dit précédemment, SWR fournit un autre hook qui permet de paginer facilement les données. Mettons à jour notre application avec useSWRInfinite
.
Pagination des données avec useSWRInfinite
Il est toujours possible d'utiliser le hook useSWR
pour paginer les données, mais je ne le recommande pas car c'est du code supplémentaire et SWR propose déjà useSWRInfinite
pour le faire.
useRequest.js
import { useSWRInfinite } from "swr"
const fetcher = url => fetch(url).then(res => res.json())
const baseUrl = "https://jsonplaceholder.typicode.com"
export const usePaginatePosts = path => {
if (!path) {
throw new Error("Path is required")
}
const url = baseUrl + path
const PAGE_LIMIT = 5
const { data, error, size, setSize } = useSWRInfinite(
index => `${url}?_page=${index + 1}&_limit=${PAGE_LIMIT}`,
fetcher
)
const posts = data ? [].concat(...data) : []
const isLoadingInitialData = !data && !error
const isLoadingMore =
isLoadingInitialData ||
(size > 0 && data && typeof data[size - 1] === "undefined")
const isEmpty = data?.[0]?.length === 0
const isReachingEnd =
isEmpty || (data && data[data.length - 1]?.length < PAGE_LIMIT)
return { posts, error, isLoadingMore, size, setSize, isReachingEnd }
}
Le hook useSWRInfinite
attend comme argument une fonction qui retourne la clé de requête, une fonction fetcher
, et des options. La clé de requête (index
) est ce que SWR utilise pour savoir quelles données (page) récupérer. La valeur initiale de la clé de requête est 0
, nous devons donc l'incrémenter de 1
à chaque demande. Le deuxième argument à définir sur l'URL est PAGE_LIMIT
, qui est le nombre d'éléments à récupérer par requête.
useSWRInfinite
renvoie plus de valeurs que cela. J'ai supprimé les données dont je n'ai pas besoin ici. Expliquons ce que font ces variables:
posts
est le tableau des données extraites du serveur.isLoadingInitialData
vérifie s'il reste des données à récupérer.isLoadingMore
vérifie si nous récupérons actuellement des données.isEmpty
vérifie si le tableau de données est vide ou pas.isReachingEnd
vérifie si la limite de pages est atteinte ou pas.
Ensuite, nous retournons les valeurs afin de les utiliser dans nos composants.
App.js
import { usePaginatePosts } from "../useRequest"
import Post from "../components/Post"
export default function IndexPage() {
const {
posts,
error,
isLoadingMore,
size,
setSize,
isReachingEnd,
} = usePaginatePosts("/posts")
if (error) return <h1>Something went wrong!</h1>
if (!posts) return <h1>Loading...</h1>
return (
<div className="container">
<h1>My Posts with useSWRInfinite</h1>
{posts.map(post => (
<Post post={post} key={post.id} />
))}
<button
disabled={isLoadingMore || isReachingEnd}
onClick={() => setSize(size + 1)}
>
{isLoadingMore
? "Loading..."
: isReachingEnd
? "No more posts"
: "Load more"}
</button>
</div>
)
}
Ici, nous importons d'abord usePaginatePosts
, puis nous passons le point de terminaison de l'API comme argument. Ensuite, nous utilisons les valeurs renvoyées par le hook pour afficher les publications et charger de nouvelles données. Une fois que vous avez cliqué sur le bouton load more
, SWR enverra la demande à la page suivante, puis renverra les données. Avec ceci en place, les données sont maintenant paginées à l'aide du hook useSWRInfinite
.
Avec cette étape, nous pouvons tester si la pagination fonctionne en exécutant cette commande sur la CLI:
yarn dev
Visitez sur le navigateur http://localhost:3000
Et c'est tout! Notre application a l'air de bien fonctionner!
Nous avons fini d'utiliser la bibliothèque SWR côté client avec Next.js. Vous pouvez trouver le projet fini sur ce CodeSandbox.
Merci d'avoir lu!