DEV Community

Cover image for react-query swrjs alova In-Depth Comparison
Scott Hu
Scott Hu

Posted on • Updated on

react-query swrjs alova In-Depth Comparison

As our projects become increasingly complex, users are demanding higher speed and better user experiences. Relying solely on traditional request libraries like Axios or Fetch to handle data requests often results in a lot of redundant boilerplate code, which has long been criticized. This is where enhanced request libraries come into play.

Some of you might be wondering, "What exactly is an enhanced request library?" An enhanced request library typically builds on top of traditional request libraries and integrates deeply with UI frameworks like React and Vue through hooks. It also provides additional performance optimization features, such as response caching, to help reduce boilerplate code and improve request performance.

Currently, some of the most popular enhanced request libraries include @tanstack/react-query, swr, and the rising star alova. Each has its unique features. Here, we'll take a deep dive into comparing them to help you determine which one best suits your project's needs. That way, when a new project requirement arises, you'll know exactly which tool to choose.

Quick channel for comparison tools

Let's start right now and compare them from the following 8 perspectives.

  1. Product positioning and features

  2. hooks

  3. Framework support

  4. Server support

  5. Request method

  6. Cache strategy

  7. API automation solution

  8. Performance

Comparison of Positioning and Features

First, let's discuss their different positioning.

@tanstack/react-query primarily focuses on managing asynchronous state. Its strength lies in helping you handle data fetching, caching, and synchronization. When you need data, it fetches it for you; when the data becomes stale, it updates it.

swr also focuses on asynchronous state management, using lightweight hooks to simplify data fetching.

alova provides a comprehensive request solution, mainly to help developers raise API integration efficiency. It reduces the number of steps for developers to use API from 7 to just 1, helping developers reduce a lot of API maintenance time.

Different positioning means these libraries have different design considerations. react-query and swr focus mainly on the hooks they provide and cache management functions. In contrast, alova optimizes API consumption efficiency by taking a more holistic approach to the request strategy. It not only offers hooks but also includes hook middleware, global seamless refresh interceptors, and other features referred to as request strategies. It also provides automatic API generation and search extension plugins. Because of this, I believe alova addresses API-related challenges in multiple aspects.

Let's look at a comparative example in React.

react-query

import { useQuery } from '@tanstack/react-query';

const fetchUsers = async () => fetch('https://api.example.com/users')
    .then(res => res.json());
function UserList() {
  const { data: users, isLoading, error } = useQuery('users', fetchUsers);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>An error occurred: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
Enter fullscreen mode Exit fullscreen mode

swr

import useSWR from 'swr';

const fetcher = url => fetch(url)
    .then(res => res.json());

function UserList() {
  const { data: users, error } = useSWR('https://api.example.com/users', fetcher);

  if (!users) return <div>Loading...</div>;
  if (error) return <div>An error occurred: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
Enter fullscreen mode Exit fullscreen mode

alova

import { createAlova, useRequest } from 'alova';
import adapterFetch from 'alova/fetch';
import ReactHook from 'alova/react';

const alovaInstance = createAlova({
  baseURL: 'https://api.example.com',
  statesHook: ReactHook,
  requestAdapter: adapterFetch(),
});

function UserList() {
  const methodInstance = alovaInstance.Get('/users');
  const { loading, data: users, error } = useRequest(methodInstance);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>An error occurred: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
Enter fullscreen mode Exit fullscreen mode

You can see. react-queryandswrsend requests directly with asynchronous functions, whilealovaneeds to create a request instance in advance, which defines how to send requests using the fetch adapter under react. In addition, adapters such asxmlhttprequestandaxios are also provided. These are all due to their positioning-dominated design concepts, and these differences will be reflected in the following comparisons.

Comparison of hooks

Number of hooks

  • @tanstack/react-query provides hooks such as useQuery, useMutation, and useInfiniteQuery.

  • swr mainly provides hooks such as useSWR and useSWRInfinite.

  • alova provides a total of 15+ request strategies in different request scenarios, including useRequest, useWatcher, usePagination, useFetcher, useForm, etc.

hook actions

One of the features of alova's hooks is that its scenario-based hooks also provide a wealth of actions, which allow developers to more finely control data operations and quickly implement the comprehensive functionality of different complex requests, which is not available in react-query and swr. For example, the following is actions for paging request.

import { usePagination, useForm } from "alova/client";

// Pagination request example
const {
  loading,
  data,
  page,
  pageSize,
  pageCount,
  total,
  insert,
  remove,
  replace,
  refresh,
  reload,
} = usePagination((page, pageSize) => getUserList({ page, pageSize }), {
  initialPage: 1,
  initialPageSize: 10,
});

// Use actions
const handleAddUser = (newUser) => {
  insert(newUser);
};
const handleRemoveUser = (userId) => {
  remove((user) => user.id === userId);
};
Enter fullscreen mode Exit fullscreen mode

hooks middleware support

alova and swr's hooks support middleware, allowing more fine-grained customization during the request process. But react-query does not support it.

swr

function myMiddleware (useSWRNext) {
return (key, fetcher, config) => {
// Before hook runs...

// Process the next middleware, or the `useSWR` hook if this is the last one.
const swr = useSWRNext(key, fetcher, config)

// After the hook runs...
return swr
}
}

<SWRConfig value={{ use: [myMiddleware] }}>

// Or...

useSWR(key, fetcher, { use: [myMiddleware] })
Enter fullscreen mode Exit fullscreen mode

alova

import { useRequest } from "alova/client";

// Define a middleware
const loggingMiddleware = async (context, next) => {
  console.log("Request started:", context.config);
  const response = await next();
  console.log("Request ended:", response);
};

// Use middleware in hook
const { loading, data } = useRequest(getUserList, {
  middleware: loggingMiddleware,
});
Enter fullscreen mode Exit fullscreen mode

Framework support

Client

  • @tanstack/react-query supports mainstream UI frameworks in the form of independent packages, although it was originally designed for React.
  1. react: @tanstack/react-query
  2. vue: @tanstack/vue-query
  3. svelte: @tanstack/svelte-query
  4. angular: @tanstack/angular-query
  5. solid: @tanstack/solid-query
  • swr only supports react.
  • alova supports frameworks such as react/vue/svelte with a single package + UI framework adapter, unifying the user experience under each UI framework.

SSR

All three support mainstream SSR frameworks.

Server support

@tanstack/react-query and swr mainly provide clienthooks for client applications. Although they can be used in a server-side rendering (SSR) environment, they cannot be used directly in a non-SSR server-side environment, but they do not provide APIs used in pure server-side environments (such as Express or Koa route handlers).

In contrast, alova not only fully supports server-side programs, but also provides server-side request strategies for the server-side environment. They are called server hooks, which makes it easier and more flexible to control requests on the server side.

The following is an example of sending a verification code with retry:

const { retry, sendCaptcha } = require("alova/server");

app.get("/api/captcha/send", async (req, res) => {
  const email = req.params.email;
  // Create a method instance for sending a verification code
  const captchaMethod = alovaInstance.Post("/api/captcha", {
    email,
    content: "captcha content",
  });

  // Use retry hook to wrap captchaMethod
  const retringMethod = retry(captchaMethod, {
    retry: 3,
    backoff: {
      delay: 2000,
    },
  });
  // Use sendCaptcha hook to wrap retringMethod, and send the request and get the response result through await
  const result = await sendCaptcha(retringMethod, {
    key: email,
  });
});
Enter fullscreen mode Exit fullscreen mode

Request method

@tanstack/react-query and swr provide asynchronous functions to receive request data. Users need to directly use axios or fetch third-party request libraries to obtain data and provide it to @tanstack/react-query and swr. This gives all control of the request to the user, and even simulates the request in the asynchronous function.

const fetchUsers = async () =>
  new Promise((resolve) => {
    setTimeout(() => {
      resolve({ data: "your data" });
    }, 1000);
  });
const { data: users, isLoading, error } = useQuery("users", fetchUsers);
Enter fullscreen mode Exit fullscreen mode

But alova uses Method as a proxy object, which has the following advantages for me:

  1. Provides a unified request method. Users do not need to care about what method is used for request except setting the request adapter.

  2. It has various uses. Users can use Method to send requests directly like axios, and can also directly pass it into hooks to control requests.

// Direct request
const res = await alvoaInstance.Get("/users");

// Pass in request in useRequest
const { loading, data, error } = useRequest(alvoaInstance.Get("/users"));
Enter fullscreen mode Exit fullscreen mode
  1. For example, using XMLHttpRequest request can also get a complete and unified experience, including global interceptors. Alova provides XMLHttpRequest adapter, but it needs to be encapsulated in @tanstack/react-query and swr.

  2. Easy to port to other projects, just change the request interceptor globally.

Cache strategy

@tanstack/react-query

  • Fine cache control: @tanstack/react-query allows to configure staleTime and cacheTime to determine the cache duration and expiration time of data.

  • Automatic refresh and invalidation: Configure automatic refresh of data under certain conditions through options such as refetchOnWindowFocus and refetchOnReconnect.

  • Cache data persistence: Implement persistent storage of client cache data through the persistQueryClient plugin.

  • Cache debugging tool: Provides ReactQueryDevtools debugging tool for observing and processing data requests and cache status.

swr

  • Custom global cache: SWR uses a global cache to share data, and allows customizing how to store cache through the provider option of SWRConfig.
  • Modify cache data: Provides mutate function to modify the cache, including clearing all cached data or updating specific cache items.
  • Cache debugging tool: View and debug through browser extensions.

alova

  • Multi-level cache: Supports L1 and L2 multi-level cache, and can restore data from persistent storage after the memory cache is invalidated to adapt to different usage scenarios.
  • Fine cache control: Allows you to set different expiration times for different levels of cache, providing more flexible cache management.
  • Automatic cache invalidation: Automatically invalidate the corresponding cache by specifying the relationship between APIs, reducing the trouble of manual invalidation.
  • Flexible cache storage: You can use any cache storage to store data, such as localStorage, sessionStorage, indexedDB on the client, AsyncStorage under react-native, and @alova/psc shared by multiple processes on the server, or even redis storage shared by clusters.

API Automation Solution

Since @tanstack/react-query and swr give all control of the request to the user, the API automation solution is provided by third-party request tools. For example, axios and fetch can automatically generate request codes through openapi-generator or @openapitools/openapi-generator-cli.

Alova provides a more advanced openAPI solution. , including the following:

  1. Generate API call code, TypeScript type and detailed API documentation for each API at the same time, so that you can enjoy complete API type hints even in JavaScript projects, which are not available in openapi-generator and @openapitools/openapi-generator-cli.

  2. A brand new API integration experience. In the past, when the backend developer delivered the API to you, you needed to open the intermediate API document to query and copy key information to your project. You needed to constantly switch between the API document and the editor in the middle, but now, Alova's development tools can eliminate the intermediate API document for you, shortening the collaboration distance between the front and back ends like a wormhole. Through it, you can quickly find the required API in the editor and display the complete documentation of this API, and quickly complete parameter transfer by referring to the API parameter table.

Image description

  1. Update the API regularly and actively notify the front-end development, no longer relying on the notification of the server-side developer.

Performance

Dependency collection

Dependency collection refers to the automatic tracking of the status of component dependencies within hooks. When the status of the dependency changes, it will trigger the re-rendering of the view. This is more of a way to reduce the rendering of react components.

swr and alova both support dependency collection, while @tanstack/react-query does not.

Alova's unique performance features

Request sharing

Request sharing means that when multiple identical requests are issued at the same time, only one request will be actually issued, and the response data will be shared with these requests. It can not only improve the fluency of the application, but also reduce the pressure on the server.

Image description

@tanstack/react-query and swr are not supported, alova is supported on both the client and the server.

hooks performance optimization

Compared with @tanstack/react-query and swr hooks, one feature of alova's scenario-based hooks is that it can optimize performance for specific scenarios, for example:

  1. usePagination can automatically pre-fetch the list data of the previous and next pages, so that users do not need to wait when turning pages (turning pages in seconds)

  2. useForm provides a form draft, and unsubmitted data will not be deleted even if it is refreshed

Default GET cache

Since alova's cache key is automatically calculated through the request information of the method instance, by default, alova's GET has a 5-minute cache, and there is no need to repeat the request when multiple requests for duplicate data are made.

Conclusion

After an in-depth discussion, we have a more comprehensive understanding of the three request enhancement libraries alova, @tanstack/react-query and swr. Each library has its own unique advantages and applicable scenarios. Which library to choose ultimately depends on your project requirements, the team's technology stack, and considerations of performance, ease of use, and flexibility.

  1. swr is known for its simplicity and ease of use. If you are looking for a lightweight and easy-to-use solution, or your project focuses on fast rendering and minimizing server requests, srw will be an ideal choice.

  2. For applications that require powerful state management and caching capabilities, @tanstack/react-query is a good choice.

  3. If you don't want to spend more time on API use, want to find a unified request solution, or are sending requests in Express or koa, alova may be more suitable for your needs.

There is no best library, only the one that best suits your project. Take the time to evaluate and compare different tools, and finally choose the one that can help you and your team work more efficiently and happily.

I hope this article can help you better understand the characteristics of these three request enhancement libraries and make wise choices in actual projects.

Bye everyone!!!

Top comments (0)