5

React-Query: How to fetch queries conditionally

 2 years ago
source link: https://www.js-howto.com/react-query-how-to-fetch-queries-conditionally/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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}- </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}- </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}- </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

Like this:

Loading...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK