- Published on
SWR
- Authors
- Name
- Shelton Ma
1. Install
pnpm add swr
2. Fetcher
// src/lib/fetch.ts
export default async function fetcher(...args: Parameters<typeof fetch>) {
const res = await fetch(...args);
return res.json();
}
3. Hooks
1. Fetch Data
// src/features/documents/hooks/use-get-document.ts
import fetcher from "@/lib/fetch";
import useSWR from "swr";
export const useGetDocuments = () => {
const { data, error, isLoading } = useSWR("/api/document", fetcher);
return { data, error, isLoading };
};
2. Mutate
// src/features/documents/hooks/use-create-document.ts
import { documents } from "@/db/schema";
import { InferInsertModel, InferSelectModel } from "drizzle-orm";
import { useState } from "react";
import { mutate } from "swr";
type CreateDocumentData = InferInsertModel<typeof documents>;
type DocumentData = InferSelectModel<typeof documents>;
type Options = {
onSuccess?: (data: DocumentData) => void;
onError?: (error: Error) => void;
onSettled?: () => void;
};
export const useCreateDocument = () => {
const [status, setStatus] = useState<
"success" | "error" | "settled" | "pending" | null
>(null);
const createDocument = async (
data: CreateDocumentData,
options?: Options
) => {
try {
setStatus("pending");
const response = await fetch("/api/documents", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Failed to create document");
}
const result = await response.json();
mutate("/api/documents");
options?.onSuccess?.(result?.document);
setStatus("success");
return result?.document;
} catch (error) {
setStatus("error");
options?.onError?.(
error instanceof Error ? error : new Error("An error occurred")
);
} finally {
setStatus("settled");
options?.onSettled?.();
}
};
return { createDocument, status };
};
3. Add types to hooks
import fetcher from "@/lib/fetch";
import { DocumentData } from "../types";
import useSWR from "swr";
export const useGetDocuments = () => {
const { data, error, isLoading } = useSWR<{ documents: DocumentData[] }>("/api/documents", fetcher);
return {
data: data.documents,
isLoading: isLoading,
error
};
};
4. Pagination
import fetcher from "@/lib/fetch";
import useSWR from "swr";
import { DocumentData } from "../types";
export const useGetDocuments = ({
page = 1,
pageSize = 10,
sort = "updatedAt",
sortOrder = "desc",
}: {
page?: number;
pageSize?: number;
sort?: string;
sortOrder?: string;
}) => {
const { data, error, isLoading } = useSWR<{
documents: DocumentData[];
totalPages: number;
totalDocuments: number;
currentPage: number;
pageSize: number;
}>(
`/api/documents?page=${page}&pageSize=${pageSize}&sort=${sort}&sortOrder=${sortOrder}`,
fetcher
);
return { data, error, isLoading };
};
Revalidate
mutate("/api/documents");
mutate(
(key: string) =>
typeof key === "string" && key.startsWith("/api/documents")
);