Bill
Bill

Reputation: 4413

React: useState callback / fetching data infinite loop

If I run the code below, I get an infinite loop (as indicated in the console log). I think this happens because my useState callback (setEvents) causes a re-render which causes the function App to be re-run, which then re-fetches the data, calls my useState callback again and so on. This code is based on numerous examples I've seen online - what am I doing wrong?

import React, {useState, useEffect} from 'react';
import {BrowserRouter as Router, Route} from "react-router-dom";
import EventMonitorRoute from './routes/event-monitor';
import ReactDOM from 'react-dom';


function App() {

    console.log('Running App'); // DEBUG

    let basename = (window.location.hostname === 'localhost') ? '/' : '/event_monitor';
    let apiURL = 'https://example-api.com';
    const [events, setEvents] = useState(null);

    async function fetchData(apiURL) {
        console.log('fetching data'); // DEBUG
        const response = await fetch(apiURL);
        const json = await response.json();
        setEvents(json);
    }

    useEffect(() => {
        fetchData(apiURL)
    });

    return (
        <Router basename={basename}>
            <div id="app-container-inner">
                <Route exact path="/" render={(props) => <EventMonitorRoute events={events} {...props}/>}/>
            </div>
        </Router>
    );
}

ReactDOM.render(
    <App/>,
    document.getElementById('app-container')
);

Upvotes: 0

Views: 774

Answers (1)

Dupocas
Dupocas

Reputation: 21317

Move the declaration inside the effect and pass an empty array as second argument:

console.log('Running App'); // DEBUG


useEffect(() => {

let basename = (window.location.hostname === 'localhost') ? '/' : '/event_monitor';
let apiURL = 'https://example-api.com';
const [events, setEvents] = useState(null);

async function fetchData(apiURL) {
    console.log('fetching data'); // DEBUG
    const response = await fetch(apiURL);
    const json = await response.json();
    setEvents(json);
}
    fetchData(apiURL)
}, []);

Upvotes: 1

Related Questions