Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

I can fetch data based on my query, but then the fetching never stops. How do I limit the fetch requests?

As I type in my search, the data will fetch from the API properly. The problem is that it keeps fetching several thousand times until the API throws an error. I successfully implemented an abortController, but I feel like there’s a less abrupt way to stop a fetch. I am using the useEffect hook based on the query and inventory state, but I don’t think my logic is very concise at all. Ideally, I need to fetch the data once and wait to fetch again when the query state changes. Not necessarily the the query and inventory as it is in the code, but that’s the only way it seemed to work.

Note: If there is nothing in the query, no results should be displayed.

Here’s the API (not sure if it’s needed for this question):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

export const search = (query, maxResults) =>
  fetch(`${api}/search`, {
    method: "POST",
    headers: {
      ...headers,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query, maxResults }),
  })
    .then((res) => res.json())
    .then((data) => data.books);

Here’s the Search component:

import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
import * as BooksAPI from "./BooksAPI";

const SearchBooks = () => {
    const [query, setQuery] = useState("");
    const [bookInventory, setBookInventory] = useState([]);

    useEffect(() => {
        let abortFetch = false;

        const getBooks = async () => {
            if (query.length !== 0) {
                const res = await BooksAPI.search(query, 20);
                setBookInventory(res);
            } 
            if (query.length === 0) {
                setBookInventory();
            }
        };

        if (!abortFetch) {
            getBooks();
        }
        
        return () => {
            abortFetch = true;
        }
    }, [query, bookInventory])

    const updateSearchQuery = (query) => {
        setQuery(query);
    };

    return (
        <div className="search-books">
            <div className="search-books-bar">
                <Link to={"/"} className={"close-search"}>Close</Link>
                <div className="search-books-input-wrapper">
                    <input
                        type="text"
                        placeholder="Search by title, author, or ISBN"
                        value={query}
                        onChange={(e) => updateSearchQuery(e.target.value)}
                    />
                </div>
            </div>
            <div className="search-books-results">
                {
                typeof bookInventory === 'object' && bookInventory.length > 0
                    ? <p>Your search results go here</p>
                    : <p>Enter a valid search term to see results.</p>
                }
            </div>
        </div>
    )
}

export default SearchBooks;

>Solution :

Because you have put bookInventory in Second argument to useEffect, and put setBookInventory in useEffect function.
This means every time bookInventory changes, call useEffect.
This’s the reason of that it keeps fetching.

The solution is to delete bookInventory from Second argument to useEffect:

useEffect(() => {
    ...
}, [query]);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading