How a custom hook saved me 100+ hours of debugging

I wrote the same useEffect code 47 times before I learned this. Most React developers repeat themselves endlessly. I was one of them. Writing fetch logic in every component. Debugging async issues in 20 different places. Copy-pasting the same error handling everywhere. Then I built one custom hook. Everything changed. ➕ 70% less component code ➕ One source of truth for API calls ➕ Consistent error handling across the app ➕ Zero repeated patterns The difference between junior and senior developers? Senior developers write code once. This custom hook saved me 100+ hours of debugging and rewrites. Check the code in the image How would you improve this hook? Drop your thoughts below 💾 Save this for your next React project #React #JavaScript #WebDevelopment #FrontendDevelopment #ReactHooks #Programming #Coding #WebDev #SoftwareDevelopment #Developer

  • text

Don’t forget to add an abort controller that aborts on URL change or unmount, also you need a local cancelled flag that’s set to true on unmount / url change so that if a request finishes you can check if it’s cancelled before updating state. If you don’t it can cause errors if the request is processing and the component is unmounted or URL changes. You also need to reset state if the URL changes. For anyone saying just use react query. React query is VERY useful and I recommend it but sometimes there are cases where you can’t use it. I do work on a website that can’t use it, I’ll probably try again at some point but I have to use a custom hook instead.

Like
Reply

Good abstraction for repetition, but this approach still runs into race conditions on unmount, lacks AbortController support, and misses caching or deduplication. With React 18+ and the upcoming use() API, RSC, and built-in fetch caching, most teams are moving data fetching out of manual effect hooks and into the framework level data layer. Curious if you’ve explored those patterns?

Like
Reply

You need to abort the request when the component unmounts or when the URL changes. And you also forget to reset the state when the URL changes. You could also add different method handling, headers, body etc.

Great work! Just a couple of minor suggestions to consider: - Use AbortController to allow conditional cancellation of HTTP requests. This is especially useful when users furiously click a "send" button or navigate between pages while the request is still loading; - Refactor the hook to accept an asynchronous function instead of just a URL. This would give us more control over headers, body parameters, and other request configurations. Also, as a general preference, I tend to avoid pulling in a library if I only need one small feature from it - keeping things lightweight and easier to maintain.

Like
Reply

I always create a new file with the name 'apiService' and perform all actions in that file, from the request interceptor to the response interceptor. All logic, like retry, abort signal, and just call it in the component.

See more comments

To view or add a comment, sign in

Explore content categories