Part 72: Optimizing Data Fetching in React: Using React Query in Your NavBar

[Pages] React Query

[Pages] React Query

With React Query set up in our application, it's time to leverage its power in our components. Today, we’ll focus on the NavBar component, where we'll replace traditional state management with React Query's useQuery hook for fetching user data. This transition not only simplifies our code but also enhances performance through caching and efficient data management.

Transitioning from useState and useEffect to useQuery

Understanding useQuery

React Query's useQuery hook is a powerful tool for fetching and caching data. It requires:

  1. Query Key: An identifier for the query, used for caching. In our case, we'll use "user" since we're fetching user data.

  2. Query Function: A function that fetches the data, returning the user data or undefined if not authenticated.

  3. Options: An object to configure caching and other behaviors, such as staleTime and cacheTime.

Implementing useQuery in NavBar

Let's see how to integrate useQuery into our NavBar component:

// components/NavBar.js

import Link from 'next/link';
import { useQuery } from 'react-query';
import { fetchJson } from '../lib/api';

function NavBar() {
  // Using useQuery to fetch and cache user data
  const query = useQuery('user', async () => {
    try {
      return await fetchJson('/api/user');
    } catch (err) {
      return undefined; // User is not authenticated
    }
  }, {
    cacheTime: Infinity, // Cache data indefinitely
    staleTime: 30_000, // Data is fresh for 30 seconds
  });

  const user = query.data;

  const handleSignOut = async () => {
    await fetchJson('/api/logout');
    // FIXME: handle sign-out logic
  };

  console.log('[NavBar] user:', user);

  return (
    <nav>
      <Link href="/">Home</Link>
      {user ? (
        <button onClick={handleSignOut}>Sign Out</button>
      ) : (
        <Link href="/sign-in">Sign In</Link>
      )}
    </nav>
  );
}

export default NavBar;

Key Changes

  • Data Fetching: We replaced useState and useEffect with useQuery, eliminating the need for manual state updates and error handling.

  • Caching: By setting staleTime to 30,000 milliseconds (30 seconds), we ensure the user data is not refetched unnecessarily within this period.

  • Memory Management: cacheTime set to Infinity keeps the user data in memory indefinitely, perfect for data needed across multiple pages.

Testing and Observations

Initial Load

Upon page load, the NavBar uses useQuery to fetch user data from /api/user. The data is initially undefined until the API response is received, which then updates the UI.

With staleTime configured, navigating to different pages within 30 seconds does not trigger additional user data requests. React Query serves the data from its cache, enhancing performance and reducing server load.

Window Focus Behavior

By default, React Query refetches data when the window regains focus, ensuring up-to-date information. This is particularly useful if user authentication status can change, such as token expiration.

Handling Sign-Out

Currently, the sign-out logic is marked with a FIXME. To fully implement this, ensure the app state reflects the user's signed-out status. This might involve clearing local storage or redirecting to a sign-in page.

Conclusion

Integrating React Query into your components can significantly streamline data fetching and caching. By using useQuery, we simplify the NavBar component, reduce redundant API calls, and enhance the user experience with responsive data updates.

In future posts, we'll continue exploring React Query's capabilities, including more complex use cases and configurations. Stay tuned as we delve deeper into optimizing your React applications!

Last updated