skip to Main Content

I have page where I am getting data via getServerSideProps(). But also I have component where user can search data. Search data are sent back to main page and used. Problem is I am getting infinitive loop. Data in console.log() are still fetching..

How can I fetch data only once? Can you please show me what I am doing wrong? tnx


export async function getServerSideProps() {

  await connectDB();

  try {

    const animals = await NewEvent.find({})
    
    return {
      props: {
        animals: JSON.parse(JSON.stringify(animals)),
      }
    }

  } catch (error) {
     return {
      props: {
        notFound: true
      },
    };
  }

}





const Index = ({ animals }) => {
      console.log(animals)   // I am getting data permanently.

   // function to get search data from search component
    const getSearchedData = (data) => {
      console.log(data)     // I am getting data permanently.
      setSearchData(data)
    }


  return (
   <>
     
       {/* Component for searching data */} 
        <SearchAnimals  getSearchedData={getSearchedData} />

SearchAnimals component here with useCalback



const Index = ({ getSearchedData }) => {
  const [query, setQuery] = useState('');



const getData = useCallback(async () => {

  try {
    const config = {
      headers: {
        "Content-Type": "application/json",
      },
    };

    // call backend and getting data
    const res = await axios.post(`/api/searchAnimals`, { query: query }, config);

    if (getSearchedData) {
      getSearchedData(res.data.data);
    }


  } catch (error) {
    console.error('Error fetching data:', error);
  }
}, [query, getSearchedData]);


  useEffect(() => {
    getData()
  }, [query, getData])



2

Answers


  1. In the current setup, getServerSideProps fetches data when the page is loaded on the server side, and then your component has logic to fetch data on the client side as well. This can lead to redundant data fetching.

    To resolve this issue, you can modify your component to check if the data has already been fetched before triggering additional requests. You can use a state variable to keep track of whether the initial server-side data fetching has occurred. Here’s an example:

    import { useState, useEffect } from ‘react’;
    import axios from ‘axios’;

    const Index = ({ animals: initialAnimals }) => {
      const [animals, setAnimals] = useState(initialAnimals);
      const [searchData, setSearchData] = useState([]);
      const [isServerDataFetched, setServerDataFetched] = useState(true); // Initially set to true
    
      // Function to get search data from the search component
      const getSearchedData = (data) => {
        setSearchData(data);
      };
    
      const getData = async () => {
        try {
          const config = {
            headers: {
              'Content-Type': 'application/json',
            },
          };
    
          // Call backend and get data
          const res = await axios.post(`/api/searchAnimals`, { query: query }, config);
          setAnimals(res.data.data);
          setSearchData(res.data.data);
        } catch (error) {
          console.error('Error fetching data:', error);
        }
      };
    
      // Fetch initial data on the client side only if it hasn't been fetched on the server side
      useEffect(() => {
        if (!isServerDataFetched) {
          getData();
          setServerDataFetched(true); // Set to true to prevent further client-side fetching
        }
      }, [isServerDataFetched]);
    
      return (
        <>
          {/* Component for searching data */}
          <SearchAnimals getSearchedData={getSearchedData} />
          {/* Render your data here using the 'animals' state */}
        </>
      );
    };
    
    export async function getServerSideProps() {
      await connectDB();
    
      try {
        const animals = await NewEvent.find({});
        return {
          props: {
            animals: JSON.parse(JSON.stringify(animals)),
          },
        };
      } catch (error) {
        return {
          props: {
            notFound: true,
          },
        };
      }
    }
    
    Login or Signup to reply.
  2. You have a function that gets some data (let’s call it getData). Now, you also have a special function in React called useEffect that runs some code when your component is first loaded or whenever something changes.Now, if you put getData inside useEffect and inside getData you change something that causes a re-render (like updating the state), it can create a loop. This loop happens because changing the state triggers a re-render, and that re-render runs useEffect again, which calls getData, and the cycle repeats.To fix this, you might want to make sure that what’s inside getData doesn’t cause a constant loop of re-renders.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search