React-query series Part 3: Data fetching with the useQuery hook.

Cover image by Lawrence Eagles in the article: What’s new in React Query 3

Hey everyone !

I’m back again. I am always grateful for the encouragement. Thank you for the ?, for taking the time to read the lengthy Part Two: QueryClient configuration o…


This content originally appeared on DEV Community and was authored by Emmanuel Chinonye Nnajiofor

Cover image by Lawrence Eagles in the article: What’s new in React Query 3

Hey everyone !

I'm back again. I am always grateful for the encouragement. Thank you for the ?, for taking the time to read the lengthy Part Two: QueryClient configuration of this series. To my new followers; Thank you! I'll do my best not to disappoint you.

In part two, we talked about overriding some of the defaults that come with react-query by setting our custom defaults for both queries and mutations. We set our custom defaults on such options like retry , staleTime, cacheTime, refecthOnMount and a couple of others for our queries and retry for mutations.

Table of contents

Intro

In this part, we will be learning how to fetch data from an API using the useQuery hook. I promised to show you how we can override the defaults we set earlier, so we will have a look at that too. Always remember to use the table of contents above to jump to sections relevant to you.

The useQuery hook

We start by installing axios and refactoring a bit.

npm i axios

Our QueryClient goes to a new file ./src/util/queryClient.js

import { QueryClient} from 'react-query';

const queryClientConfig = {
    defaultOptions: {
      queries: {
        retry: 2,
        staleTime: 1000 * 30,// 30 seconds
        cacheTime: 1000 * 30, //30 seconds
        refetchOnMount: "always",
        refetchOnWindowFocus: "always",
        refetchOnReconnect: "always",
        refetchInterval: 1000 * 30, //30 seconds
        refetchIntervalInBackground: false,
        suspense: false,

      },
      mutations: {
        retry: 2,
      },
    },

 export const queryClient = new QueryClient(queryClientConfig);

If you just got here, we explained this snippet here

We clean our App.js thus

import { QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { queryClient } from "./util/queryClient";


 function App() {
   return  (
           <QueryClientProvider client={queryClient}>
             {/* The rest of your application */}
             <ReactQueryDevtools initialIsOpen={false} />
           </QueryClientProvider>
        )
 }

We will also create a queryKeys.js file at ./src/util/queryKeys.js.
This file will host all the query keys for our application.

export const fetchPostsKey = "FETCH_POSTS";

Create a fetchPosts.service.js file at ./src/services/fetchPosts.service.js and create your simple async function to fetch a list of posts.
We will be using the JSONPlaceholder REST API for this demo.

import axios from "axios";

/**
 * @desc fetch a list of posts
 */
export const fetchPosts = async () => {
  const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
  return res?.data;
};

Fetching data

Create a Posts.js component at ./src/components/Posts.js

Remember to import your Posts.js component to your App.js

...

 function App() {
   return  (
            <QueryClientProvider client={queryClient}>
              <Posts/>
              <ReactQueryDevtools initialIsOpen={false} />
            </QueryClientProvider>
        )
 }

Posts.js

import { useQuery } from "react-query";
import { fetchPosts } from "../../services/fetchPosts.service";
import { fetchPostsKey } from "../../util/queryKeys";

const Posts = () => {

  const {  isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery(fetchPostsKey, fetchPosts);


  return (
    <div>
      {isLoading ? (
        <div>Loading...</div>
      ) : isError ? (
        <div>An error while fetching posts</div>
      ) : (
        data?.map((post) => (
          <div key={post?.id}>
            <div>{post?.title}</div>
            <div>{post?.body}</div>
          </div>
        ))
      )}
    </div>
  );
};
export default Posts;

The useQuery hook accepts a query key as its first argument and the query function as its's second argument.
The query key is required, the query function also is required as there was not default query function defined for our queries in QueryClient. Let's take a quick brush at the items in the destructured object useQuery returns to us.

isLoading: It is a boolean value that returns true when the query has no data and is currently fetching and false when not.

isError: Also a boolean value. It return true when the query attempt results in an error.

isSuccess: Returns true if the query has received a response with no errors and is ready to display its data. isSuccess is false when query is not yet resolved or results in an error.

refetch : This is a function that manually refetches the query.

remove : This function is used to manually remove the query from cache.

data : It is the response from the last successful query. data will be undefined if query fails for the first time.

error : It is the error response from your query. It is defined when your query is in an isError state.

The useQuery hook returns more values in the destructured object than described here, but this few I chose for the scope of this article. You can read more about the useQuery hook here.

Passing variable(s) to a query function

So, what if you want to pass a variable or variables to your query function? E.g. you have a function that fetches a single post and it requires you to pass in a post id; What do you do?
Let's see how it is done.

We will a new key entry in a queryKeys.js file at ./src/util/queryKeys.js.

...
export const fetchSinglePostKey = "FETCH_SINGLE_POST";

Create also a fetchSinglePost.service.js file at ./src/services/fetchSinglePost.service.js and create your simple async function to fetch a single post by id.

fetchSinglePost.service.js

import axios from "axios";

/**
 * @desc fetches a single post
 */
export const fetchSinglePost = async ({queryKey}) => {
const [_key, id] = queryKey
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`);
  return res?.data;
};

Post.js

import { useQuery } from "react-query";
import { fetchSinglePost } from "../../services/fetchSinglePost .service";
import { fetchSinglePostKey } from "../../util/queryKeys";

const Post = () => {

// fetching the post with the id of 1

  const {  isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery([fetchSinglePostKey, 1], fetchSinglePost );


  return (
    <div>
      {isLoading ? (
        <div>Loading...</div>
      ) : isError ? (
        <div>An error while fetching post</div>
      ) : (
          <div >
            <div>{data?.title}</div>
            <div>{data?.body}</div>
          </div>
        )
      )}
    </div>
  );
};
export default Post;

Here, we are no more using a string value for our query key but an array, passing in the query string first and the post id as required by our query function fetchSinglePost.service.js.

The fetchSinglePost function declared in useQuery hook is passed in a context, this context has queryKey array nested in it. This queryKey array contains your query string as the first item in the array and your id variable for fetching our single post.

Remember to import your Post.js component to your App.js

...

 function App() {
   return  (
            <QueryClientProvider client={queryClient}>
               ...
              <Post/>
              <ReactQueryDevtools initialIsOpen={false} />
            </QueryClientProvider>
        )
 }

Overriding query defaults

We have seen two demonstrations using useQuery but don't forget that they all are operating within the queries default we set earlier. To override some of the global configurations, we pass an object as a third argument to the useQuery hook. Every option you declare a new value, that option is overridden for that useQuery instance only.

...
 const {  isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery([fetchSinglePostKey, 1], fetchSinglePost, {
    refetchInterval : 3* 1000 //3 seconds
});

...

What this snippet above implies is that, although we configured react-query globally to refetch queries every 30 seconds, This particular query will refetch every 3 seconds; breaking away from the global configurations.

Conclusion

The returned data from our queries are stored in a cache. In the next part, we will discuss how the to interact with this cache.
Thank you all for your support. If you are beginner and haven't written something, do that today! Please give me a ? if this post or part of it has helped you. Comments are welcomed too.
Follow me on twitter @NnajioforEmma10

Table of contents


This content originally appeared on DEV Community and was authored by Emmanuel Chinonye Nnajiofor


Print Share Comment Cite Upload Translate Updates
APA

Emmanuel Chinonye Nnajiofor | Sciencx (2021-08-22T19:07:05+00:00) React-query series Part 3: Data fetching with the useQuery hook.. Retrieved from https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/

MLA
" » React-query series Part 3: Data fetching with the useQuery hook.." Emmanuel Chinonye Nnajiofor | Sciencx - Sunday August 22, 2021, https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/
HARVARD
Emmanuel Chinonye Nnajiofor | Sciencx Sunday August 22, 2021 » React-query series Part 3: Data fetching with the useQuery hook.., viewed ,<https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/>
VANCOUVER
Emmanuel Chinonye Nnajiofor | Sciencx - » React-query series Part 3: Data fetching with the useQuery hook.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/
CHICAGO
" » React-query series Part 3: Data fetching with the useQuery hook.." Emmanuel Chinonye Nnajiofor | Sciencx - Accessed . https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/
IEEE
" » React-query series Part 3: Data fetching with the useQuery hook.." Emmanuel Chinonye Nnajiofor | Sciencx [Online]. Available: https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/. [Accessed: ]
rf:citation
» React-query series Part 3: Data fetching with the useQuery hook. | Emmanuel Chinonye Nnajiofor | Sciencx | https://www.scien.cx/2021/08/22/react-query-series-part-3-data-fetching-with-the-usequery-hook/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.