2

I'm trying to get some data from a Django API, with Axios, and when I use useEffect only once (call it with an empty array []), it's not getting any data. However, when I add the state where the response data is stored, it goes in an infinite loop and it's changing data every second. I know that calling a useEffect with an empty array calls it only one time, but it seems that it's not working. How can I manage to get the data only one time?

My code:

function IdentificationStep(props) {

  const [predictions, setPrediction] = useState([]);
  const [loadingState, setLoadingState] = useState(true);
  const [getValue , SetValue] = useState(true)
  useEffect(() => {
    setTimeout(() => {
      setLoadingState(false);
    }, 3000);
  }, []);


  const getPredictions = async () => {
    const response = await axios.get('/snake-image/prediction/'+(props.id))
    setPrediction(response.data)
  }

   useEffect(() => { getPredictions(); console.log(predictions); SetValue(false)}, [])
   //infinite loop when i track predictions state
   //useEffect(() => { getPredictions(); console.log(predictions); SetValue(false)}, [predictions])

I tried .then(), like boxdox proposed to me, but it still returns an empty array

const getPredictions = async () => {
    const response = await axios.get('/snake-image/prediction/'+(props.id)).then(response => {
      setPrediction(response.data);
      console.log(predictions);
    })
    //setPrediction(response.data)
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

I'm getting an empty array like this:
empty response

Thanks for the help, I solved it

The problem was that use effect was going on infinite loop. I just checked the length of my predictions state and then use if else block on the useeffect()

useEffect(() => {
    async function getPredictions() {
      let response = await axios.get('/snake-image/prediction/'+(props.id));
      response = await response;
      setPrediction(response.data);
      setLoadingState(false);
      console.log(response.data);
    }


    if(predictions.length < 3)
    {
      getPredictions();
    console.log(predictions);
    }

    else{console.log("already done")}
    
  }, [predictions])
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Ilyes Negadi
  • 107
  • 2
  • 8

1 Answers1

3

As your getPredictions is an async function that's why you are not getting data in your useEffect. You can do it by declaring the function in your useEffect:

function IdentificationStep(props) {
  const [predictions, setPrediction] = useState([]);
  const [loadingState, setLoadingState] = useState(true);
  const [getValue, SetValue] = useState(true);
  useEffect(() => {
    setTimeout(() => {
      setLoadingState(false);
    }, 3000);
  }, []);

  useEffect(() => {
    const getPredictions = async () => {
      const response = await axios.get("/snake-image/prediction/" + props.id);
      setPrediction(response.data);
    };
    await getPredictions();
    console.log(predictions);
    SetValue(false);
  }, []);
}

sakshya73
  • 5,570
  • 5
  • 22
  • 41
  • 1
    `console.log(predictions);` would still log the *wrong* value. See the linked duplicate for reasons why. – Yoshi Aug 23 '21 at 10:25
  • i tried it its throwing an error , (Unexpected reserved word 'await'). on line 40 , even if the function is async ... dont know why ? – Ilyes Negadi Aug 23 '21 at 10:45
  • 1
    await doesn't work inside a regular function. you need to define the anonymous function passed to useEffect as async, but that will not work inside use effect. – boxdox Aug 23 '21 at 10:55
  • 1
    @boxdox. That's also one method but we can do it like this also. What you can do is put a loading state as `true` when you start fetching and when the data is fetched you can make that loading state `false` and based on the loading state you can render your predictions. – sakshya73 Aug 23 '21 at 11:14