To ensure a fetch request is made only if the search term hasn’t been used before, and to display related data if the search term was previously used, you can leverage React Query along with local state management. This approach involves maintaining a local cache of search terms and their corresponding data.

import React, { useEffect, useRef, useState } from 'react';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
import { Label, Button, Input } from 'reactstrap';

const queryClient = new QueryClient();
const fetchProducts = async () => {
 const response = await fetch(`https://dummyjson.com/products`);
 if (!response.ok) {
   throw new Error('Network response was not ok');
 }
 return response.json();
};

const fetchProductByName = async (payload) => {
 const response = await fetch(`https://dummyjson.com/products/search?q=${payload}`);
 if (!response.ok) {
   throw new Error('Network response was not ok');
 }
 return response.json();
};

const MyComponent = () => {
 const [param, setParam] = useState('');
 const [usedTerms, setUsedTerms] = useState({});
 const prevParamRef = useRef(param);

 const { data: products, refetch } = useQuery(
   ['products', param],
   () => fetchProducts(param),
   {
     enabled: false, // Disable automatic refetching
   }
 );

 const { data: searchProducts, refetch: refetchQuery } = useQuery(
   ['data', param],
   () => fetchProductByName(param),
   {
     enabled: false, // Enable query only if param changes
   }
 );

 useEffect(() => {
   if (param !== prevParamRef.current && !usedTerms[param]) {
     refetchQuery().then((newData) => {
       setUsedTerms((prevTerms) => ({
         ...prevTerms,
         [param]: newData.data
       }));
       prevParamRef.current = param;
     });
   }
 }, [param, refetchQuery, usedTerms]);

 const lists = products || searchProducts;

 const returnProducts = () => {
   return lists && lists?.products.map((product) => (
     <div key={product?.id}>
       <h2>{product?.title}</h2>
       <p>{product?.description}</p>
       <span><b>Price:</b> ${product?.price}</span>
     </div>
   ))
 };

 return (
   <div>
     <Label>
       <Input
         name="search"
         value={param}
         placeholder="Search Product"
         onChange={(e) => setParam(e.target.value)}
       />
     </Label>
     <Button onClick={() => refetch()}>Get Products</Button>
     {returnProducts()}
   </div>
 );
};

const ReactQuery = () => (
 <QueryClientProvider client={queryClient}>
   <MyComponent />
 </QueryClientProvider>
);

export default ReactQuery;

Explanation:

1. State Management:

  • param: Stores the current search term.
  • usedTerms: An object that caches previously used search terms and their corresponding data.

2. useRef:

  • prevParamRef: Stores the previous search term to compare against the current term.

3. useQuery:

  • Configured with enabled: false to disable automatic fetching on component mount.
  • The refetch function is used to manually trigger the fetch.

4. useEffect:

  • Triggers a fetch if the current search term is different from the previous term and has not been used before.
  • If these conditions are met, it calls refetchQuery to fetch data, updates usedTerms with the new data, and stores it locally to avoid future fetches for the same term.

5. Button Click Handling:

  • The button triggers a refetch of all products.

This approach ensures efficient data fetching and caching by storing search results locally, reducing redundant network requests and improving performance.

Support On Demand!

ReactJS