Home > OS >  useQuery Hook result set to loading without being called
useQuery Hook result set to loading without being called

Time:01-06

I'm trying to build a search bar in my new project, and I seem to be doing some things(maybe a lot) wrong.

I set the book state to null and the useQuery hook seems to be using it to search for books.

I don't want it to search for anything unless I click the button.

These are my codes:

fetchBooks.jsx

async function fetchBooks({ queryKey }) {
  const book = queryKey[1];

  const response = await fetch(
    `https://www.googleapis.com/books/v1/volumes?q=${book}`
  );
  if (!response.ok) {
    throw new Error(`Search not found for ${book}`);
  }
  return response.json();
}

export default fetchBooks;

Here is the main component.

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import fetchBooks from "../helper/fetchBooks";

const Home = () => {

    const [book, setBook] = useState(null);

    const results = useQuery(["search", book], fetchBooks);

    const handleSubmit = (e) => {
        e.preventDefault();
        setBook(e.target.elements.book.value);
    };

    return (
        <>
            <form onSubmit={handleSubmit}>
                <label htmlFor="book">
                    Book Name:
                    <input type="text" name="book" />
                </label>
                <button type="submit">Submit</button>
            </form>

            {results.isLoading ? (
                <div>Loading...</div>
            ) : results.isError ? (
                <div>{results.error.message}</div>
            ) : (
                <div>
                    <h2>Results</h2>
                    <ul>
                        {results.data.items.map((item) => {
                            return (
                                <div key={item.id}>
                                    <h3>{item.volumeInfo.title}</h3>
                                    <p>{item.volumeInfo.authors}</p>
                                </div>
                            );
                        })}
                    </ul>
                </div>
            )}
        </>
    );
};

export default Home;


CodePudding user response:

You can return a default value in the fetch function if the book is null. Then, the query won't actually request the API.

async function fetchBooks({ queryKey }) {
  const book = queryKey[1];

  if(!book) return { items: [] }

  const response = await fetch(
    `https://www.googleapis.com/books/v1/volumes?q=${book}`
  );
  if (!response.ok) {
    throw new Error(`Search not found for ${book}`);
  }
  return response.json();
}

export default fetchBooks;

CodePudding user response:

Instead of restricting the useQuery to call the fecthBooks functions, you can modify the fetchBooks functions to return an empty array if book is set to null. The fetchBooks can be modified as below:-

async function fetchBooks({ queryKey }) {
  const book = queryKey[1];
  if(!book){
    return { 
              isLoading : false,
              error : null,
              data : null
           }
  }
  const response = await fetch(
    `https://www.googleapis.com/books/v1/volumes?q=${book}`
  );
  if (!response.ok) {
    throw new Error(`Search not found for ${book}`);
  }
  return response.json();
}

export default fetchBooks;
  • Related