Blog #33: 10 PM and the 'Infinite Loop' of Punishment
When striving for 'abstraction' with Custom Hooks turns into an inescapable re-render trap.
End of the Sprint, pressure to complete the real-time data sync feature. I created a Custom Hook called useEverything (its real name was useAppSync) with the intention: "Just call this Hook, and everything from Auth, Sockets, and Data will be taken care of."
Everything looked very professional until the website started freezing. The browser reported "RangeError: Maximum call stack size exceeded." An infinite re-render loop. I spent 3 hours checking every useEffect, every useCallback. I started to get irritable and wondered if React was betraying me.
1. What happened?
An infinite re-render loop was created because a single Custom Hook integrated too much interdependent logic. Premature abstraction hid the data flow, making debugging extremely difficult.
2. What I thought the cause was
I assumed it was because the server was returning socket data too fast (spamming). I tried using throttle for the socket, but the issue persisted.
3. How I debugged it
I used React Profiler to determine which component was rendering the most. Then, I started "commenting out" each piece of logic in the useAppSync Hook until the loop stopped.
4. The moment of realization
My "all-powerful" Hook was observing too many things. Just a small change in userToken would trigger the socket, the socket updated data, data changed userToken through an underlying middleware... A death spiral. I had overused Custom Hooks to hide complexity, but in reality, I was just concentrating bombs in one place.
5. The fix
- Quick patch: Add
isInitialflag variables and useuseRefto block redundant re-renders for the night. - Real fix: Scrap that giant Hook. Break it down into
useAuth,useSocket, and separate data hooks. Accept writing a few extra lines of code in the Component in exchange for clarity in the data flow.
6. Looking back
Abstraction is a tonic, but an overdose turns it into poison. Don't try to create "Black Boxes" too early without a clear understanding of the data flow. If I were to redesign, I would prioritize clarity (explicitness) over conciseness.
Series • Part 33 of 50