React-Query: How to fetch queries conditionally

Introduction

React-Query is a powerful tool for fetching/caching the data on the frontend side, in this article we’re going to demonstrate how we can fetch the queries based on user action.

React-Query useQuery hooks by default are executed once the component is mounted, which is fine, however it’s not always the case, sometimes we wanted to fetch/refetch queries based on specific actions or conditions.

Let’s get started!

Full example can be found on codesandbox.

There are two options to execute React-query useQuery hook queries programmatically or based on a user action:

1- useQuery hook with enabled option

Using this option we can control when to execute the fetch query by passing a boolean value called `enabled` to the React-Query hook. By default this `enabled` property is set to false, which means the React-Query hook will execute once the component is mounted.

Let’s see how we can take control of it using the following example:

Assuming we’ve a simple component that fetches the posts from a server once the component is mounted, here’s how the implementation will look like:

function Example() {
  const { isLoading, error, data } = useQuery(
    ["posts"],
    () =>
      axios
        .get("https://jsonplaceholder.typicode.com/posts")
        .then((res) => res.data),
  );

  if (isLoading) return "Loading...";

  if (error) return "An error has occurred: " + error.message;
  return (
    <div>
      <h1>Posts</h1>
      {data.map((post) => {
        return (
          <div style={{ display: "flex" }}>
            <span>{post.id}-&nbsp;</span>
            <div>{post.title}</div>
          </div>
        );
      })}
    </div>
  );
}

Now, let’s update that component by adding the following:

  • Button.
  • Internal state `const [fetchPosts, setFetchPosts] = useState(false);`.
  • Set the `enabled` property in the useQuery call.

Once the user clicked on that button we will update the fetchPosts state value, which will trigger the component to re-render and the useQuery hook will execute and fetch the data in case the fetchPosts value is true.

function Example() {
  const [fetchPosts, setFetchPosts] = useState(false);

  const { isLoading, error, data } = useQuery(
    ["posts"],
    () =>
      axios
        .get("https://jsonplaceholder.typicode.com/posts")
        .then((res) => res.data),
    {
      enabled: fetchPosts
    }
  );

  if (isLoading && fetchPosts) return "Loading...";

  if (error) return "An error has occurred: " + error.message;

  return (
    <div>
      <button onClick={() => setFetchPosts(true)}>Fetch posts</button>
      <h1>Posts</h1>
      {data?.map((post) => {
        return (
          <div style={{ display: "flex" }}>
            <span>{post.id}-&nbsp;</span>
            <div>{post.title}</div>
          </div>
        );
      })}
    </div>
  );
}

At line 11, we’ve added the enabled property and assigned the fetchPosts state value to it.

At line 15, we’ve updated the condition that’s responsible for showing the loading state.

At line 23, we’ve updated the posts rendering to be conditionally data?.map, meaning render posts only if we’ve the posts data.


2- Using queryClient.fetchQuery

React-query exposing some functionalities that can help in managing the queries, once of the is the fetchQuery.

fetchQuery is an asynchronous method that can be used to fetch and cache a query. It will either resolve with the data or throw with the error.

Let’s check in the following example to see how we can implement it.

function Example2() {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  if (isLoading) return "Loading...";

  if (error) return "An error has occurred: " + error;

  return (
    <div>
      <button
        onClick={async () => {
          try {
            setIsLoading(true);
            const posts = await queryClient.fetchQuery(
              ["postsUsingFetchQuery"],
              {
                queryFn: () =>
                  axios
                    .get("https://jsonplaceholder.typicode.com/posts")
                    .then((res) => res.data)
              }
            );
            setData(posts);
          } catch (e) {
            setError(e);
          }
          setIsLoading(false);
        }}
      >
        Fetch posts using fetchQuery{" "}
      </button>
      <h1>Posts</h1>
      {data?.map((post) => {
        return (
          <div style={{ display: "flex" }}>
            <span>{post.id}-&nbsp;</span>
            <div>{post.title}</div>
          </div>
        );
      })}
    </div>
  );
}

In this example, we’ve created a component internal states to hold the state of the request when it’s loading, or has an error or successfully resolved.

const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);

Then, on the button click handler, we’ve added the implementation to fetch the posts using queryClient.fetchQuery.

Note: we’ve set different query key ["postsUsingFetchQuery"], than the one we’ve in Example1, because React-Query manages the queries internally based on the queryKey.

queryClient object is coming from the following definition:

export const queryClient = new QueryClient();

That’s for how to fetch queries using React-Query.

And as always happy coding!!

Full example can be found on codesandbox.

Photo from unsplash

Related Posts

How to Capture Screenshots with Puppeteer In NodeJS

How to Capture Screenshots with Puppeteer In NodeJS

To Capture Screenshots with Puppeteer: Launch a Browser Instance Navigate to the Web Page Capture the Screenshot Introduction: Puppeteer is a powerful Node.js library that allows developers…

How to Minimize Puppeteer Browser Window To Tray

How to Minimize Puppeteer Browser Window To Tray

Puppeteer is a powerful tool for automating tasks in headless or non-headless web browsers using JavaScript. While Puppeteer is often used to perform actions within a browser,…

Intercepting Responses in Node.js with Puppeteer

Intercepting Responses in Node.js with Puppeteer

Introduction: Puppeteer is a powerful Node.js library that provides a high-level API for controlling headless Chrome or Chromium browsers. It’s widely used for web scraping, automated testing,…

Mastering React Component Re-rendering in Jest

Mastering React Component Re-rendering in Jest

In this hands-on guide, we’ll explore the art of optimizing React component re-rendering within Jest tests. By combining theory with practical coding examples, you’ll gain a deep…

Eliminating Nesting Loops in React Rendering

Eliminating Nesting Loops in React Rendering

React has ushered in a new era of web application development with its component-based structure, promoting code reusability and maintainability. But as projects evolve, achieving optimal performance…

Exploring Type and Interface Usage in TypeScript

Exploring Type and Interface Usage in TypeScript

TypeScript has gained immense popularity by bridging the gap between dynamic JavaScript and static typing. Two of its fundamental features, “Type” and “Interface,” play pivotal roles in…

Leave a Reply

%d bloggers like this: