korpe
korpe

Reputation: 93

Why is Setting state with data in a fetch using context API caught in an infinite fetch loop?

Provider

This is my context provider. Within the component, I fetch local JSON data. The JSON data looks something like this:

[
 {
  "name": "Alan",
  "ticker": [
   "AAPL",
   "MSFT",
   "GOOG",
   "FB"
  ]
 },
 {
  "name": "Madison",
  "ticker": [
    "TSLA",
    "AAPL",
    "V"
  ]
 },
 etc...
]

So it is just an array of objects. If I were to console log resp.json() it would come out good. If I console log data it would come out with the array of objs. which is good. BUT the moment I try using setProfile(data), the application going bonkers. Let me show you what happens when I try setting the profile with the data. Fetch loop

I'm assuming that this is an infinite fetch loop. Not sure honestly why this is happening when I try to setProfile(data). If there is another way of doing this please let me know. All I'm trying to do is get all the profile data in the profile context so I can use it in my other components. For example I've created a dropdown which display all the names in the json file.

Upvotes: 2

Views: 1697

Answers (2)

nihilok
nihilok

Reputation: 2083

To add a little more info to @DrewReese's correct answer, you can effectively use the dependency array to choose when to 'trigger' the useEffect. An empty dependency array will trigger only when component mounts, but you could use something like this:

    const [trigger, setTrigger] = useState(false)
    useEffect(()=>{
        console.log('Hello World')
    }, [trigger])

The above will run every time you change the state of trigger. So if you had a button that did this:

    <button onClick={()=>setTrigger(!trigger)}>Log Hello World!</button>

...it would trigger the useEffect every time you click it.

When thinking about useEffect, I also always think it's important to think about useCallback, which also takes a dependency array, and can be used to move dependencies out of the useEffect block.

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 202874

Your useEffect hook is missing a dependency array so it is running the callback each time the component renders, i.e. when it updates the profile state.

You likely want to only do this fetch once when the component mounts, so use an empty dependency array.

useEffect(() => {
  const url = ".....";
  fetch(url)
    .then(resp = resp.json())
    .then(data => setProfile(data))
    .catch(console.log);
}, []);

Upvotes: 2

Related Questions