While fetching, uploading and pagination are basic and integral parts of React development, they are the more complex and error-prone areas of development as well. There are built-in hooks(useState and useEffect), usually used to fetch data, but their implementation leaves us with repetitive code that is hard to maintain.
Tanstack/react-query is one of the most popular libraries that tried to fix these problems, with its out-of-the-box loading state, error handling, and caching, I can confidently say it has made our lives easier. In this tutorial, I will show you how to Fetch, Mutate and Paginate data using Tanstack/react-query.
Content
Prerequisite
Let’s install the library:
npm i @tanstack/react-query@4
Before we delve into fetching data, first let’s implement QueryClient which makes everything possible. What is QueryClient you might ask. QueryClient is a core component in React Query that manages caching, fetching, and updating data. It serves as a global store for query results and provides various options to customize how queries and mutations behave.
Let’s go to our Main.jsx file, we create a new instance of the QueryClient class and make it available to the whole application by adding it to our wrapper component.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
createRoot(document.getElementById("root")).render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</StrictMode>
);
I am using JSON-server for our data.
Data Fetching using React-Query
Now we can use our React Query hooks everywhere in the application, the next step would be to fetch data using the useQuery hook.
The implementation structure of useQuery looks like this. where we can easily get the pending and error state:
import axios from 'axios';
const getPost = () => {
return axios.get(url)
}
const { data, isPending, error } = useQuery({
queryKey: ["posts"],
queryFn: getPosts,
});
For this tutorial, we are going to be fetching, uploading, and paginating the Colors array. let’s go ahead and do that.
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
export default function QueryFunction() {
const getColors = () => {
return axios.get(
`http://localhost:3000/colors`
);
};
const { data, isPending, error } = useQuery({
queryKey: ["colors"],
queryFn: getColors,
});
if (isPending) {
return <div className="text-5xl">Loading...</div>;
}
if (error) {
return <div>{error.message}</div>;
}
return (
<div className="p-10">
<ol>
{data?.data.data.map((color) => {
return (
<li key={color.id}>
{color.id}. {color.label}
</li>
);
})}
</ol>
</div>
);
}
Pagination
In order to add pagination to this code, we create a useState to track our page and insert the page state to our getColors function then we can control the prev and next pages as you can see in the code below.
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
export default function QueryFunction() {
const [pageNumber, setPageNumber] = useState(1);
const getColors = (pageNumber) => {
return axios.get(
`http://localhost:3000/colors?_page=${pageNumber}&_per_page=2`
);
};
const { data, isPending, error } = useQuery({
queryKey: ["colors", pageNumber],
queryFn: () => getColors(pageNumber),
});
if (isPending) {
return <div className="text-5xl">Loading...</div>;
}
if (error) {
return <div>{error.message}</div>;
}
console.log(data.data);
return (
<div className="p-10">
<ol>
{data?.data.data.map((color) => {
return (
<li key={color.id}>
{color.id}. {color.label}
</li>
);
})}
</ol>
<div className="mt-4 space-x-2">
<button
className="bg-gray-300 py-1 px-2 rounded"
onClick={() => setPageNumber((prev) => prev - 1)}
disabled={pageNumber === 1}
>
Prev
</button>
<button
className="bg-gray-300 py-1 px-2 rounded"
onClick={() => setPageNumber((prev) => prev + 1)}
disabled={pageNumber === 5}
>
Next
</button>
</div>
</div>
);
}
Mutation using React-Query
And finally to upload our data using the useMutation hook from React-Query, we first need to create our input elements and track their state. then as you’ll see in the code below the mutation in an easy step.
import { useState } from "react";
import { useMutation } from "@tanstack/react-query";
const [id, setId] = useState(null);
const [label, setLabel] = useState("");
const mutation = useMutation({
mutationFn: (newColor) => {
return axios.post("http://localhost:3000/colors", newColor);
},
});
<div className="flex gap-2 py-4">
<input
className="border-2 "
onChange={(e) => setId(e.target.value)}
type="number"
name=""
id=""
placeholder="id"
/>
<input
className="border-2 "
onChange={(e) => setLabel(e.target.value)}
type="text"
name=""
id=""
placeholder="label"
/>
<button
className="border-2 "
onClick={() => mutation.mutate({ id: id, label: label })}
>
send
</button>
</div>
And that’s it, if you follow this tutorial, you can for sure fetch, upload and, paginate data in react using the Tanstack/react-query library. If you are interested in more tutorials like this check out my website – frewdevtutorials.com