I've been trying to get my head around hooks, in particular useEffect and its dependency list, but for some reason, the following code keeps running endlessly. I've found this very relevant question but haven't been able to make my code work following the suggestion there. Here is the buggy code, you may have to enable your browser console to see the loop.
// a fake fetch for the sake of the example
function my_fetch(f, delay) {
setTimeout(f, delay)
}
// if account is not loaded then useEffect should not fetch the balance
function useFetchBalance(account_id, account_loaded) {
const [balance, setBalance] = useState(null)
useEffect(() => {
if (!account_loaded) return; // only fetch if dependency is resolved
my_fetch(() => setBalance(41 + account_id), 3000)
}, [account_id, account_loaded])
return balance
}
function App() {
const [account, setAccount] = useState({ id: null, loaded: false })
my_fetch(() => setAccount({ id: 1, loaded: true }), 3000)
const balance = useFetchBalance(account.id, account.loaded)
console.log(balance)
return null
}
In essence, I have a state (account) which is updated using a fetch (fake in this case). While the account has not been fetched yet, account.loaded is set to false. This ensures that when useFetchBalance is called it will not fetch the balance. I'd expect the console to log initially a null value, and 6 seconds later (3 for fetching the account and 3 for fetching the balance), to log 42. However, it first prints null 3 times and then prints 42 endlessly in what seems to be batches of two. I am very new to react so any help would be greatly appreciated.
useEffectunless you only ever run it once (i.e. empty array as dependencies). Don't feel bad, IMHOuseEffectis literally the most error-prone API in all of React. Don't forget you can always write class components with lifecycle methods, you don't have to use hooks (although the rest of them are awesome).