0

I'm a completely new to the whole react world but I'm trying to develop a SPA with a integrated calendar. I'm using react-router for routing, react-big-calendar for the calendar, axios for my API calls and webpack. Whenever I'm loading my Calender Component it gets mounted and unmounted several times and I think that causes my API call to never actually get any data. I just can't figure out what is causing this.

The Code:

  useEffect(() => {
    console.log("mounting Calendar")
    let source = Axios.CancelToken.source()
    if(!initialized) {
        console.log("getting Data")
       getCalendarEvents(source)
    }

    return () => {
        console.log("unmounting Calendar")
        source.cancel();
    }
})

 const getCalendarEvents = async source => {
    setInitialized(true)  
    setLoading(true)
    try {
        const response = await getCalendar({cancelToken: source.token})
        const evts = response.data.map(item => {
            return {
                ...item,
            }
        })
        calendarStore.setCalendarEvents(evts)
    } catch (error) {
        if(Axios.isCancel(error)){
            console.log("caught cancel")
        }else{
            console.log(Object.keys(error), error.message)
        }
    }
    setLoading(false)
}

This is the result when i render the component: Console log

If you need any more code to assess the problem, I will post it. I appreciate any kind of input to solve my problem.

Thank you

  • The reason why your component re-renders is because you're changing its state. From `react` docs - "The default behavior is to re-render on every state change." What you should do, instead, is to specify a dependency array in the `useEffect` hook so that it only runs once (i.e. `[]`) or some `prop` or `state` that the `useEffect` hook should rely on. – goto Apr 26 '20 at 20:04

1 Answers1

0

Its because of the useEffect. If you want it to run just once on mount you need to pass an empty array as a dependency like so :

 useEffect(() => {
    console.log("mounting Calendar")
    let source = Axios.CancelToken.source()
    if(!initialized) {
        console.log("getting Data")
       getCalendarEvents(source)
    }

    return () => {
        console.log("unmounting Calendar")
        source.cancel();
    }
},[])

This means it will only run once. If there is some state or prop you would like to keep a watch on you could pass that in the array. What this means is that useEffect will watch for changes for whatever is passed in its dependency array and rerun if it detects a change. If its empty it will just run on mount.

Hadi Pawar
  • 1,090
  • 1
  • 11
  • 23
  • Thanks for your answer, i think i understand that. But shouldn't the useEffect return method only trigger when the component really unmounts? When you look at the console log you can see that my axios call gets cancelled. Why is that? – vsjonas Apr 27 '20 at 07:37
  • 1
    @vsjonas re-rendering means unmouting and mouting. The `useEffect` hook needs to run every time some piece of `state` changes to work properly unless you tell it to only watch for some changes - https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects – goto Apr 27 '20 at 11:50
  • . you need to wrap your head around lifecycle methods and hooks a little bit more and i suggest you go through the docs its not very difficult and you're close you're just confusing it a bit. For now did this solve your issue ? if it did consider accepting the answer :) – Hadi Pawar Apr 27 '20 at 12:44