Tired of juggling Axios and useEffects for API calls and managing dependencies? Say hello to React Query! 🎉 It makes your life easier with automatic caching, synchronization, background updates, and so much more. 🚀
Traditional Way of API Calling
In the traditional way, you typically use Axios inside a useEffect hook to make API calls and manage state manually. Here's an example:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const TraditionalAPIComponent = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get('https://api.example.com/data');
setData(response.data);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
};
fetchData();
}, []);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Data:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
export default TraditionalAPIComponent;
Using React Query (useQuery)
React Query simplifies data fetching by providing hooks that manage caching, synchronization, and background updates out of the box. Here's how you can do the same thing with React Query:
import React from 'react';
import { useQuery } from 'react-query';
import axios from 'axios';
const fetchData = async () => {
const { data } = await axios.get('https://api.example.com/data');
return data;
};
const ReactQueryComponent = () => {
const { data, error, isLoading } = useQuery('fetchData', fetchData);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Data:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
export default ReactQueryComponent;
Adding Dependencies with useQuery
Sometimes, you need to fetch data based on certain dependencies. In the traditional way, you'd do this with useEffect like so:
useEffect(() => {
// Your fechUserData API call
fetchUserData(userId);
}, [userId]);
With React Query, you can handle dependencies by using the queryKey and enabled option:
const { data, error, isLoading } = useQuery(['userData', userId], () => fetchUserData(userId), {
enabled: !!userId, // Ensure query is enabled only if userId is truthy
});
Control Cache Time
To control cache timing in React Query, you can utilize the cacheTime option within the useQuery hook. This option dictates how long the fetched data remains in the cache before it's considered outdated and possibly removed. Here's how to implement it:
const { data, error, isLoading } = useQuery('fetchData', fetchData, {
cacheTime: 3600000, // Cache data for 1 hour (3600000 milliseconds)
});
Invalidation with useInvalidateQuery
React Query provides the useInvalidateQuery
hook to invalidate specific queries. This is useful when you want to refetch data based on certain events, such as user actions or changes in application state.
const { data, error, isLoading } = useQuery('fetchData', fetchData);
const invalidateQuery = useInvalidateQuery('fetchData');
const handleButtonClick = () => {
// Invalidates the 'fetchData' query, triggering a refetch
invalidateQuery();
};
Using useMutation for update calls
useMutation
is a hook provided by React Query that simplifies data mutation operations in your React components. It encapsulates common tasks such as making HTTP requests, handling loading and error states, and updating data in response to mutations.
const updateUser = async (userData) => {
const response = await axios.put('https://api.example.com/users', userData);
return response.data; // Updated user data
};
const [mutate, { isLoading, isError, error, data }] = useMutation(updateUser);
// Execute mutation
const handleUpdateUser = async () => {
try {
await mutate({ id: 123, name: 'John Doe', email: 'john@example.com' });
} catch (error) {
console.error('An error occurred:', error);
}
};
Using useInfiniteQuery for paginated API calls
useInfiniteQuery
is a hook provided by React Query that simplifies pagination operations in your React components. It enables infinite scrolling by fetching data in chunks as the user scrolls, providing a seamless and efficient browsing experience.
import React from 'react';
import { useInfiniteQuery } from 'react-query';
import axios from 'axios';
// Define fetch function
const fetchPosts = async ({ pageParam = 1 }) => {
const response = await axios.get(`https://api.example.com/posts?page=${pageParam}`);
return response.data;
};
const PostList = () => {
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
isError,
error,
} = useInfiniteQuery('posts', fetchPosts, {
getNextPageParam: (lastPage, allPages) => lastPage.nextPage, // Extract next page number
});
return (
<div>
{data.pages.map((page, index) => (
<React.Fragment key={index}>
{page.posts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</React.Fragment>
))}
{isError && <div>Error: {error.message}</div>}
{hasNextPage && (
<button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
{isFetchingNextPage ? 'Loading more...' : 'Load More'}
</button>
)}
</div>
);
};
export default PostList;
Conclusion
In wrapping up, React Query's hooks are like magic wands for handling data in React apps! Whether it's fetching data with useQuery
, updating with useMutation
, or endless scrolling with useInfiniteQuery
, React Query simplifies everything. It's the secret sauce that makes building React apps a breeze, freeing you to focus on creating awesome user experiences. So wave goodbye to data headaches and hello to smooth sailing with React Query! ✨🚀
Top comments (0)