A Deep Dive into the React Query Library for Data Fetching

A Deep Dive into the React Query Library for Data Fetching

As professional senior web developers, we're always looking for ways to optimize the performance and user experience of our web applications. One of the key aspects of any modern web application is efficient data fetching. In this article, we will explore React Query, a powerful library that helps manage data fetching, caching, and real-time data syncing in React applications.

React Query is a popular open-source library created by Tanner Linsley. Its official documentation can be found at https://tanstack.com/query/v3/. Let's dive into the key features of React Query and learn how to use it with some code samples.

Setting up React Query

First, you need to install the React Query package:

  1. npm install react-query

Next, wrap your root component with the `QueryClientProvider` and create a new `QueryClient` instance:

  1. import { QueryClient, QueryClientProvider } from 'react-query';
  2.  
  3. const queryClient = new QueryClient();
  4.  
  5. function App() {
  6. return (
  7. <QueryClientProvider client={queryClient}>
  8. {/* Your application components */}
  9. </QueryClientProvider>
  10. );
  11. }
  12.  
  13. export default App;

Fetching Data with React Query

Let's say we want to fetch a list of users from the `/api/users` endpoint. First, create a function that fetches data from the API:

  1. async function fetchUsers() {
  2. const response = await fetch('/api/users');
  3. const data = await response.json();
  4. return data;
  5. }

Now, use the `useQuery` hook provided by React Query to fetch the data and manage its state:

  1. import { useQuery } from 'react-query';
  2.  
  3. function UsersList() {
  4. const { isLoading, error, data } = useQuery('users', fetchUsers);
  5.  
  6. if (isLoading) return 'Loading...';
  7. if (error) return 'An error occurred: ' + error.message;
  8.  
  9. return (
  10. <ul>
  11. {data.map(user => (
  12. <li key={user.id}>{user.name}</li>
  13. ))}
  14. </ul>
  15. );
  16. }

React Query automatically handles caching, retries, and even real-time data syncing. For instance, if you want the data to be refetched every 5 minutes, you can set the `refetchInterval` option:

  1. const { isLoading, error, data } = useQuery('users', fetchUsers, {
  2. refetchInterval: 1000 * 60 * 5, // 5 minutes in milliseconds
  3. });

Handling Mutations

React Query also provides a useMutation hook for handling mutations like POST, PUT, and DELETE requests. Let's say you want to add a new user:

  1. async function createUser(newUser) {
  2. const response = await fetch('/api/users', {
  3. method: 'POST',
  4. headers: {
  5. 'Content-Type': 'application/json',
  6. },
  7. body: JSON.stringify(newUser),
  8. });
  9.  
  10. const data = await response.json();
  11. return data;
  12. }

Use the `useMutation` hook to handle the mutation:

  1. import { useMutation } from 'react-query';
  2.  
  3. function CreateUserForm() {
  4. const mutation = useMutation(createUser);
  5.  
  6. const handleSubmit = async (event) => {
  7. event.preventDefault();
  8. const newUser = {
  9. name: event.target.elements.name.value,
  10. };
  11.  
  12. try {
  13. const data = await mutation.mutateAsync(newUser);
  14. console.log('User created successfully:', data);
  15. } catch (error) {
  16. console.error('Error creating user:', error);
  17. }
  18. };
  19.  
  20. if (mutation.isLoading) return 'Submitting...';
  21.  
  22. return (
  23. <form onSubmit={handleSubmit}>
  24. <label htmlFor="name">Name:</label>
  25. <input type="text" id="name" />
  26. <button type="submit">Create User</button>
  27. {mutation.isError && <p>An error occurred: {mutation.error.message}</p>}
  28. {mutation.isSuccess && <p>User created successfully!</p>}
  29. </form>
  30. );
  31. }

In the example above, we handle the form submission and use the `useMutation` hook to manage the mutation state. The `useMutation` hook provides similar state management properties as the `useQuery` hook, like `isLoading`, `isError`, and `isSuccess`.

Invalidating and Refetching Queries

Sometimes, you need to refetch a query after a mutation. React Query makes this easy with the `useQueryClient` hook:

  1. import { useMutation, useQueryClient } from 'react-query';
  2.  
  3. function CreateUserForm() {
  4. const queryClient = useQueryClient();
  5. const mutation = useMutation(createUser, {
  6. onSuccess: () => {
  7. queryClient.invalidateQueries('users');
  8. },
  9. });
  10.  
  11. // ...rest of the component
  12. }

In this example, we pass an `onSuccess` callback to the `useMutation` hook. When the mutation is successful, it invalidates the 'users' query, causing it to be refetched the next time it's needed.

Pagination and Infinite Scrolling

React Query also supports pagination and infinite scrolling out of the box. Let's implement a paginated list of users:

  1. import { usePaginatedQuery } from 'react-query';
  2.  
  3. function UsersList() {
  4. const [page, setPage] = useState(1);
  5.  
  6. const { isLoading, error, resolvedData, latestData } = usePaginatedQuery(
  7. ['users', page],
  8. fetchUsers,
  9. {
  10. staleTime: 1000 * 60 * 5, // 5 minutes in milliseconds
  11. }
  12. );
  13.  
  14. // ...rest of the component
  15. }

In the example above, we use the `usePaginatedQuery` hook, which works similarly to the `useQuery` hook but provides additional properties for pagination. You can use the `resolvedData` and `latestData` properties to render the list and handle pagination. Please refer to the official documentation for more details and examples.

Conclusion

React Query is a powerful library that simplifies data fetching and state management in React applications. Its built-in features like caching, retries, real-time data syncing, and automatic invalidation make it an essential tool for any professional senior web developer.

If you want to dive deeper into React Query, the official documentation at tanstack.com/query is a great resource. Happy coding!

We use cookies to improve your browsing experience. By continuing to use this website, you consent to our use of cookies. Learn More