0

please take a look at this code below

basically what is happening my action is being dispatched here:

   useEffect(() => {
        fetchData()
        setLoaded(true)
    }, [])

but for some reason this is infinite looping and causing my action to be dispatched continuously

export const fetchData = () => ({ type: 'GET_USER_DATA' })

and this is triggering my epic

const getUserData = (action$, state$) =>
    action$.pipe(
        ofType('GET_USER_DATA'),
        mergeMap(
            (action) =>
                ajax
                    .getJSON(
                        `myurlishere`,
                    )
                    .pipe(map((response) => fetchUserFulfilled(response))),
        )
    )

which trigger this:

const fetchUserFulfilled = (payload) => ({ type: 'GET_DATA_SUCCESS', data: payload })

this code all works but it's continuously calling it in an infinite loop

however, if I move the code from useEffect to a button call like so:

 <button onClick={fetchData}>fetch</button>

it only calls it once, which is what I want

but I need the data to be called onmount. so how do I fix it?

please note I have tried adding various things to the second argument of useEffect but it's having no effect

   useEffect(() => {
        fetchData()
        setLoaded(true)
    }, [user.id])
Red Baron
  • 7,181
  • 10
  • 39
  • 86
  • I'd guess it's something concerned with the component state or props, could you please include more code? – Tal Ohana May 08 '20 at 15:40
  • @TalOhana hi, yeh which part exactly sorry? I can confirm that when I change this `ofType('GET_USER_DATA'),` it's not called multiple times so something definitely in the epic – Red Baron May 08 '20 at 18:53

2 Answers2

0

Based solely off the provided code, I don't see any issues. My gut suggest a few options, even though you mentioned some of them I would triple check:

  1. Missing dependencies array as second arg to useEffect, or you're using a variable for it but the variable has an undefined value which would have the same problem.
  2. If you are using useEffect dependencies, perhaps one of them is constantly changing unknowingly. e.g. objects often change in identity between renders, {} !== {}
  3. There is code not shown that is also dispatching the same action, and in fact that useEffect is only running once.
  4. Some parent is rendering one of the ancestors or this component with a key={something} and the value provided changes on each render. If that happens, the component is torn down and recreated every time from scratch.

If you are 100% positive you are providing useEffect(work, []), an empty array as second argument, but the effect is in fact confirmed to be running in an infinite loop, synchronously, then the forth possibility is likely.

If you typed these code examples in the question by hand when posting this, do not trust that you implemented them the same way as what you think your app is doing. Triple check. Ideally have someone else check who didn't write the code. Often the problem is what we think we've told our code to do is not what we've actually told it to do. If you haven't already, your best bet is to step through the code with a debugger so you can see what's happening.

Hope this helps!

jayphelps
  • 15,276
  • 3
  • 41
  • 54
  • Hey Jay, thanks a lot for the reply! I eventually figured it out although im not sure why it now works haha. I'll post the code in the question to show you the comparison and maybe you'll spot why the initial one is infinite looping (the new code is basically just a trimmed down version of the original code) – Red Baron May 08 '20 at 19:19
  • The code posted is not correct btw. If it seems to work as intended it's only working by luck or misunderstanding. – jayphelps May 08 '20 at 21:50
  • interesting. I'll have to do some more digging then! – Red Baron May 08 '20 at 22:21
  • finally got it working. it was something weird going on in my routing. the problem I have now is this seems such a weird way of doing things. probably coz I dont understand it. but I'm waiting for my user to get logged in with firebase, then Im making the call to fetch data and put it in my redux state. but by then my component below has already rendered and so isn't showing the data. very odd – Red Baron May 09 '20 at 14:47
0

this is the code now working:

export const getUserDataEpic = () => {
    return ajax
        .getJSON(myurl)
        .pipe(
            map((response) => fetchUserFulfilled(response)),
        )
}

I know I'm not listening to the action fired now, but why would that be causing an infinite loop?

Red Baron
  • 7,181
  • 10
  • 39
  • 86