Home > Web Front-end > JS Tutorial > body text

How to Create and Test a React Query Hook for Global Loading Indicators

Susan Sarandon
Release: 2024-10-20 22:36:29
Original
145 people have browsed it

How to Create and Test a React Query Hook for Global Loading Indicators

React Query is a powerful tool for handling data fetching, caching, and synchronization in React applications. In this article, we'll create a custom hook using React Query's useIsFetching, useIsMutating, and useIsRestoring functions to determine if any service call is pending, allowing us to manage global loading states and show indicators. Then, we'll write unit tests using Jest to ensure the hook works as expected.

Prerequisites

Before we start, make sure you have the following installed:

  • React Query (@tanstack/react-query)
  • Jest (for testing)
  • React Testing Library (@testing-library/react-hooks) for testing hooks

If you don’t have these installed, you can add them via npm:

npm install @tanstack/react-query @testing-library/react-hooks jest
Copy after login
Copy after login

Step 1: Creating the Custom Hook

First, let's create a custom hook called useServiceConfig that checks if any service call is pending:

import { useIsFetching, useIsMutating, useIsRestoring } from '@tanstack/react-query';
import { useMemo } from 'react';

const modes = {
    fetching: 'fetching',
    mutating: 'mutating',
    restoring: 'restoring',
    all: 'all',
} as const;

type TMode = keyof typeof modes;

/**
 * @name useServiceConfig
 * @description A custom hook that returns a boolean value indicating if any service call is pending.
 * @param {TMode} mode The mode to check for pending service calls. Default is `'all'`.
 * @returns {readonly [boolean]} A tuple containing a single boolean value indicating if any service call is pending.
 */
const useServiceConfig = (mode: TMode = modes.all): readonly [boolean] => {
    const isFetching = useIsFetching();
    const isMutating = useIsMutating();
    const isRestoring = useIsRestoring();

    const isPending = useMemo(() => {
        switch (mode) {
            case modes.fetching:
                return isFetching > 0;
            case modes.mutating:
                return isMutating > 0;
            case modes.restoring:
                return isRestoring;
            case modes.all:
            default:
                return isFetching > 0 || isMutating > 0 || isRestoring;
        }
    }, [mode, isFetching, isMutating, isRestoring]);

    return [isPending] as const;
};

export default useServiceConfig;
Copy after login
Copy after login

Explanation

  • useIsFetching(): Returns the number of active queries currently being fetched.
  • useIsMutating(): Returns the number of ongoing mutations (e.g., POST, PUT, DELETE requests).
  • useIsRestoring(): Checks if React Query is restoring the cache from storage.

We combine these values using useMemo to determine if any of them indicate a pending state. The hook then returns a tuple containing this boolean value.

We use these functions to determine if any service call is pending. If any of these functions return a value greater than 0, we set isPending to true.

Step 2: Writing Unit Tests

Now that we have our hook, let's write unit tests using Jest to ensure it behaves as expected.

Setting Up the Tests

Create a file called useServiceConfig.test.ts (or .js if not using TypeScript). We'll use React Testing Library's renderHook utility to render our hook in a test environment.

npm install @tanstack/react-query @testing-library/react-hooks jest
Copy after login
Copy after login

Explanation of the Tests

  • Mocking Dependencies:
    • We use jest.mock to mock the functions useIsFetching, useIsMutating, and useIsRestoring.
    • Mocking allows us to simulate different return values and control the behavior during tests.
  • Test Cases:
    • Default Mode:
      • ('all'): If all statuses are zero or false, the hook should return false.
    • Specific Modes:
      • 'fetching': If useIsFetching returns a value greater than 0, the hook should return true.
      • 'mutating': If useIsMutating returns a value greater than 0, the hook should return true.
      • 'restoring': If useIsRestoring returns true, the hook should also return true.
  • Running the Tests:

    • Run the tests using Jest:

      import { useIsFetching, useIsMutating, useIsRestoring } from '@tanstack/react-query';
      import { useMemo } from 'react';
      
      const modes = {
          fetching: 'fetching',
          mutating: 'mutating',
          restoring: 'restoring',
          all: 'all',
      } as const;
      
      type TMode = keyof typeof modes;
      
      /**
       * @name useServiceConfig
       * @description A custom hook that returns a boolean value indicating if any service call is pending.
       * @param {TMode} mode The mode to check for pending service calls. Default is `'all'`.
       * @returns {readonly [boolean]} A tuple containing a single boolean value indicating if any service call is pending.
       */
      const useServiceConfig = (mode: TMode = modes.all): readonly [boolean] => {
          const isFetching = useIsFetching();
          const isMutating = useIsMutating();
          const isRestoring = useIsRestoring();
      
          const isPending = useMemo(() => {
              switch (mode) {
                  case modes.fetching:
                      return isFetching > 0;
                  case modes.mutating:
                      return isMutating > 0;
                  case modes.restoring:
                      return isRestoring;
                  case modes.all:
                  default:
                      return isFetching > 0 || isMutating > 0 || isRestoring;
              }
          }, [mode, isFetching, isMutating, isRestoring]);
      
          return [isPending] as const;
      };
      
      export default useServiceConfig;
      
      Copy after login
      Copy after login

      You should see output indicating all tests have passed.

Conclusion

In this article, we built a custom React Query hook that checks the status of service calls based on different modes (fetching, mutating, restoring, or all). We then wrote and ran tests using Jest to ensure our hook behaves correctly in various scenarios. This approach helps manage global loading states, making it easier to show indicators in your application.

By following these steps, you can create similar hooks for different use cases and confidently test them.

Next Steps

  • Try extending the hook to accept other parameters, such as specific query keys, to customize its behavior further.
  • Explore more of React Query’s utilities to enhance your application's performance and user experience.

Happy coding!

The above is the detailed content of How to Create and Test a React Query Hook for Global Loading Indicators. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!