<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hasnain alam</title>
    <description>The latest articles on DEV Community by hasnain alam (@hasnain_alam).</description>
    <link>https://dev.to/hasnain_alam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4018487%2F18b8f8f1-efe7-4671-932e-cc0e615bcc5e.png</url>
      <title>DEV Community: hasnain alam</title>
      <link>https://dev.to/hasnain_alam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hasnain_alam"/>
    <language>en</language>
    <item>
      <title>Why You Should Replace useEffect API Calls With Tanstack React Query</title>
      <dc:creator>hasnain alam</dc:creator>
      <pubDate>Sun, 13 Sep 2026 07:28:11 +0000</pubDate>
      <link>https://dev.to/hasnain_alam/why-you-should-replace-useeffect-api-calls-with-tanstack-react-query-4mhh</link>
      <guid>https://dev.to/hasnain_alam/why-you-should-replace-useeffect-api-calls-with-tanstack-react-query-4mhh</guid>
      <description>&lt;p&gt;Every React dev has written this at least once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works sure. But once your app gets a bit bigger this pattern starts causing problems, specially performance and backend load.&lt;/p&gt;

&lt;p&gt;I'm a Mern stack developer and for a long time i just used useEffect for every single api call in my apps, until i actually tried Tanstack React Query properly. Now i barely write a raw useEffect for fetching data anymore.&lt;/p&gt;

&lt;p&gt;Here is why i made the switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your API Gets Called Twice (and its not a bug)
&lt;/h2&gt;

&lt;p&gt;If you're using React 18 with StrictMode, you probably noticed your effects run twice in development. This is intentional, React does this to help catch side effect bugs. But it also means your api is getting hit 2 times on mount which confuses a lot of devs, and even in production if a component remounts often, useEffect fires again and again without any smart caching.&lt;/p&gt;

&lt;p&gt;That means more load on your backend for no real reason.&lt;/p&gt;

&lt;p&gt;React query fixes this because it caches by query key. If the data is already there and still "fresh" it wont refetch, it just returns the cached data instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boilerplate for Loading and Error States
&lt;/h2&gt;

&lt;p&gt;With plain useEffect you end up writing this same block over and over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this for every single fetch in a medium size app and you got a lot of repeated code, plus more chances of bugs, like forgetting to reset loading in the catch block or not handling cleanup on unmount.&lt;/p&gt;

&lt;p&gt;React Query gives you all this for free from the hook itself, &lt;code&gt;isLoading&lt;/code&gt;, &lt;code&gt;isError&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, done.&lt;/p&gt;

&lt;h2&gt;
  
  
  No More Dependency Array Guessing
&lt;/h2&gt;

&lt;p&gt;Dependency arrays are one of the most confusing part of hooks for beginners and even experienced devs mess it up sometime. Missing a dependency causes stale data bugs. Adding too many causes unnecessary re renders and re fetching.&lt;/p&gt;

&lt;p&gt;React Query removes this whole problem. You give it a query key and a fetch function, that's it. It manages refetching based on mount, focus, or your staleTime settings, not a manually managed array.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Power: Cache, StaleTime and Invalidation
&lt;/h2&gt;

&lt;p&gt;These are the 3 features that actually changed how i build react apps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache: data fetched once is stored under its key, come back to same page and you instantly see data while it refreshes quietly in background if its stale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;staleTime: tells react query how long the data stays "fresh". Fresh data means no unnecessary refetch, which directly reduces backend calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;invalidateQueries: after a mutation like updating or deleting something, you just invalidate the related query key and react query refetches it automatically. No manual syncing of state after mutations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you use these together, most of the manual data fetching logic you used to write with useEffect just disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Project Where This Actually Mattered
&lt;/h2&gt;

&lt;p&gt;I worked on a Next js SaaS platform recently where the dashboard was firing multiple api calls on every tab switch, all because of useEffect running on every mount. The backend was getting hammered with repeated requests and users noticed the slow loading.&lt;/p&gt;

&lt;p&gt;After replacing useEffect with react query, adding staleTime, and using invalidateQueries for mutations, the whole dashboard felt way faster and the backend load dropped a lot. That project is live here if you want to see it, it was a &lt;a href="https://hasnainalam.com/projects/petro411-mineral-owner-contact-database-next-js-saas-platform" rel="noopener noreferrer"&gt;Next.js SaaS Platform&lt;/a&gt; built for managing mineral owner contact data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is useEffect Useless Now
&lt;/h2&gt;

&lt;p&gt;No, not at all. useEffect still has its place for things like subscriptions, event listeners, timers, syncing with non react code etc. Its just not the right tool for data fetching anymore, specially when a purpose built library like react query exists and handles it so much better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;As a &lt;a href="https://hasnainalam.com/" rel="noopener noreferrer"&gt;Mern stack developer&lt;/a&gt; i learned this the hard way, after debugging way too many "why is my api getting called 3 times" issues that all came back to useEffect misuse. Switching to react query fixed most of it instantly, and gave me caching and invalidation on top, basically for free.&lt;/p&gt;

&lt;p&gt;If you're building serious apps and want to reduce backend load while writing cleaner code, i'd say give react query a shot on your next project. As someone who works as a &lt;a href="https://hasnainalam.com/" rel="noopener noreferrer"&gt;Full stack Mern &amp;amp; Next.js developer&lt;/a&gt;, this is one of those changes i recommend to almost every team i work with now.&lt;/p&gt;

&lt;p&gt;I have covered some common issues with Tanstack here, &lt;a href="https://hasnainalam.com/blog/react-query-common-issues-invalidate-queries" rel="noopener noreferrer"&gt;Common React Query Issues, Query Key and Invalidate Queries Problems Explained&lt;/a&gt;, where i explained why invalidate queries sometime dont work and how to fix pagination, update and delete cases properly.&lt;/p&gt;

&lt;p&gt;Let me know if you already use react query or still on useEffect, curious to hear what others think.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>reactquery</category>
    </item>
    <item>
      <title>Surviving the iOS Push Notification Setup Process</title>
      <dc:creator>hasnain alam</dc:creator>
      <pubDate>Thu, 23 Jul 2026 03:03:36 +0000</pubDate>
      <link>https://dev.to/hasnain_alam/surviving-the-ios-push-notification-setup-process-1m4k</link>
      <guid>https://dev.to/hasnain_alam/surviving-the-ios-push-notification-setup-process-1m4k</guid>
      <description>&lt;h2&gt;Why iOS is a different beast&lt;/h2&gt;
&lt;p&gt;To be real with you, setting up notifications on Android is like a walk in the park compared to iOS. Apple takes security seriously, which is great for users but a bit of a nightmare for us developers. You can't just drop a config file and call it a day. You have to deal with the Apple Developer Portal, certificates, and provisioning profiles. I've lost count of how many times a notification failed to deliver because of a mismatched Bundle ID or a missing capability in Xcode.&lt;/p&gt;
&lt;h2&gt;The magic of the P8 file&lt;/h2&gt;
&lt;p&gt;Back in the day, we used P12 certificates that expired every year. It was a mess. If you forgot to renew it, your app's notifications just stopped working one morning. Thankfully, we now have Authentication Keys (the .p8 file). It's way better because it doesn't expire and one key can work for all your apps. You upload this to your Firebase settings under the Cloud Messaging tab. But make sure you have your Team ID and Key ID ready. If you get those wrong, Firebase won't be able to talk to the Apple Push Notification service (APNs).&lt;/p&gt;
&lt;h2&gt;Xcode configurations you can't miss&lt;/h2&gt;
&lt;p&gt;Open your project in Xcode and go to the Signing &amp;amp; Capabilities tab. You need to add two specific things. First is &lt;strong&gt;Push Notifications&lt;/strong&gt;. Second is &lt;strong&gt;Background Modes&lt;/strong&gt;. Inside Background Modes, make sure you check &lt;strong&gt;Remote notifications&lt;/strong&gt;. Without this, your app won't wake up to handle the incoming data when it's in the background. It's a small checkbox, but it's the difference between a working app and a broken one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Even if you have the token, you must register for remote notifications on iOS&lt;br&gt;
import { useEffect } from 'react';&lt;br&gt;
import { Platform } from 'react-native';&lt;br&gt;
import messaging from '@react-native-firebase/messaging';

&lt;/code&gt;&lt;p&gt;&lt;code&gt;const usePushNotification = () =&amp;gt; {&lt;br&gt;&lt;br&gt;
  useEffect(() =&amp;gt; {&lt;br&gt;&lt;br&gt;
    if (Platform.OS === 'ios') {&lt;br&gt;&lt;br&gt;
      // This is crucial for iOS device registration&lt;br&gt;&lt;br&gt;
      messaging().registerDeviceForRemoteMessages();&lt;br&gt;&lt;br&gt;
    }&lt;br&gt;&lt;br&gt;
  }, []);&lt;br&gt;&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;I've spent hours debugging iOS notifications only to realize I forgot to enable the capability in Xcode. It happens to the best of us. Take your time with the Developer Portal and double-check every string. Once you get that first 'Hello World' notification on an iPhone, you can breathe a sigh of relief. You've cleared the hardest part of the project.&lt;/p&gt;
&lt;p&gt;Hasnain Alam, &lt;a href="//hasnainalam.com"&gt;Full-Stack Developer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>apns</category>
      <category>appledeveloper</category>
      <category>reactnative</category>
    </item>
  </channel>
</rss>
