<?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: Tarun Sharma</title>
    <description>The latest articles on DEV Community by Tarun Sharma (@101beardo).</description>
    <link>https://dev.to/101beardo</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%2F4074008%2F33ca5210-d85e-43f0-9c65-e235a282781b.PNG</url>
      <title>DEV Community: Tarun Sharma</title>
      <link>https://dev.to/101beardo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/101beardo"/>
    <language>en</language>
    <item>
      <title>React Query's staleTime vs gcTime: the difference that actually bites people</title>
      <dc:creator>Tarun Sharma</dc:creator>
      <pubDate>Wed, 16 Sep 2026 18:52:22 +0000</pubDate>
      <link>https://dev.to/101beardo/react-querys-staletime-vs-gctime-the-difference-that-actually-bites-people-nfk</link>
      <guid>https://dev.to/101beardo/react-querys-staletime-vs-gctime-the-difference-that-actually-bites-people-nfk</guid>
      <description>&lt;p&gt;You set up React Query, wire up a &lt;code&gt;useQuery&lt;/code&gt;, and everything works. Then a teammate asks: "why did this refetch when I switched tabs and came back, even though nothing changed?" and a week later someone else asks the opposite: "why is this data still showing after the component unmounted and remounted five minutes later?"&lt;/p&gt;

&lt;p&gt;Both questions come from the same confusion: mixing up &lt;code&gt;staleTime&lt;/code&gt; and &lt;code&gt;gcTime&lt;/code&gt; (called &lt;code&gt;cacheTime&lt;/code&gt; before React Query v5).&lt;/p&gt;

&lt;h2&gt;
  
  
  What each one actually controls
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;staleTime&lt;/code&gt; answers: "how long is this data considered fresh, so React Query doesn't bother refetching it automatically?"&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gcTime&lt;/code&gt; answers a completely different question: "how long should this data stay in memory after nothing is using it anymore, before React Query throws it away?"&lt;/p&gt;

&lt;p&gt;They're not two settings for the same knob. One is about refetch behavior while something is actively subscribed to the query. The other is about cleanup after everything unsubscribes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The default that surprises people
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;With no options, &lt;code&gt;staleTime&lt;/code&gt; defaults to 0. That means the instant the query resolves, it's already stale. It won't show a loading spinner again because you still have cached data to render, but React Query will quietly refetch in the background on the next relevant trigger, window focus, remount, reconnect. That's the tab-switch refetch people report as a bug. It isn't one. It's the default working as designed for data that changes outside your app's control.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gcTime&lt;/code&gt; defaults to 5 minutes. That's why data can outlive the component that fetched it. Unmount the component, and React Query doesn't delete the cache entry immediately, it waits, because you might navigate back within a few minutes and it can skip the network round trip entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this actually bites
&lt;/h2&gt;

&lt;p&gt;A case that comes up a lot: a details page fetches with &lt;code&gt;staleTime: Infinity&lt;/code&gt; because the data rarely changes, then the user navigates away and back within a minute, expecting a fresh value because something changed server-side. With &lt;code&gt;staleTime: Infinity&lt;/code&gt;, React Query will never consider it stale on its own, no refetch happens, no matter how long you wait. That's not a bug in the library, it's the setting doing exactly what it says. If you want "cache aggressively but still refetch after a while," you want a finite &lt;code&gt;staleTime&lt;/code&gt;, not &lt;code&gt;Infinity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The opposite bites people building anything sensitive, carts, live counts, permissions. Setting a long &lt;code&gt;gcTime&lt;/code&gt; doesn't make data go stale slower, it only controls how long unused data survives in memory. If you actually want fewer background refetches, that's &lt;code&gt;staleTime&lt;/code&gt;'s job, not &lt;code&gt;gcTime&lt;/code&gt;'s.&lt;/p&gt;

&lt;h2&gt;
  
  
  A mental model that holds up
&lt;/h2&gt;

&lt;p&gt;Think of &lt;code&gt;staleTime&lt;/code&gt; as an expiry date on food you're currently eating, and &lt;code&gt;gcTime&lt;/code&gt; as how long you'll keep leftovers in the fridge after you're done. Extending the expiry date doesn't change how long the leftovers last once you stop eating, and keeping leftovers around longer doesn't make the food fresher while you're actively eating it. Same query, two independent lifecycles.&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;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// fresh for 1 minute, no background refetch during that window&lt;/span&gt;
  &lt;span class="na"&gt;gcTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// keep it around 10 minutes after nothing subscribes&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you separate the two questions, "is this refetching too much" and "is this staying in memory too long or too short", picking values stops being guesswork.&lt;/p&gt;

&lt;p&gt;Have you shipped a bug that turned out to be one of these two settings confused for the other? What was the giveaway that finally pointed you at the right one?&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>5 more React interview questions I'd actually ask (and how I'd answer them)</title>
      <dc:creator>Tarun Sharma</dc:creator>
      <pubDate>Wed, 09 Sep 2026 15:36:44 +0000</pubDate>
      <link>https://dev.to/101beardo/5-more-react-interview-questions-id-actually-ask-and-how-id-answer-them-1pj</link>
      <guid>https://dev.to/101beardo/5-more-react-interview-questions-id-actually-ask-and-how-id-answer-them-1pj</guid>
      <description>&lt;p&gt;The first version of this list did well enough that people asked for more, so here are five more React questions I actually reach for in interviews. Same idea as before: none of these are trivia, they all come from bugs I have watched people ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why can using an array index as a &lt;code&gt;key&lt;/code&gt; break things?
&lt;/h2&gt;

&lt;p&gt;Most people know "don't use index as key" as a rule without knowing what it protects against. The key tells React which element in the new list matches which element in the old list. If you key by index and the list reorders, index 0 is still index 0, so React thinks nothing moved. It keeps the old component instances in place and just updates their props.&lt;/p&gt;

&lt;p&gt;For a list of plain text that is fine. The moment a row holds state that React owns, it breaks: an uncontrolled input keeps the value that belonged to the row that used to be there, focus stays on the wrong row, a half-finished CSS transition plays on the wrong element. Prepending an item is the classic trigger, because every index shifts by one and React re-renders every single row instead of mounting one.&lt;/p&gt;

&lt;p&gt;Use a stable id from the data. If you genuinely have no id and the list never reorders, index is acceptable, but say so out loud so the next person knows it was a choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What is a stale closure and where does it bite in React?
&lt;/h2&gt;

&lt;p&gt;A closure captures the variables that were in scope when the function was created, not when it runs. In React your function components re-run on every render, so each render has its own copy of props and state. A callback created on render 1 closes over render 1's state forever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// count is always 0 here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;span class="c1"&gt;// empty deps, so this effect only ever saw the first render&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interval callback was created once, when &lt;code&gt;count&lt;/code&gt; was 0, and it keeps reading that 0. The fixes are the functional updater &lt;code&gt;setCount(c =&amp;gt; c + 1)&lt;/code&gt;, or putting &lt;code&gt;count&lt;/code&gt; in the deps and letting the effect re-subscribe, or a ref if you need the latest value without re-running the effect. The same trap shows up in event handlers passed to &lt;code&gt;addEventListener&lt;/code&gt; and in &lt;code&gt;setTimeout&lt;/code&gt; callbacks inside effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why can't you call a hook inside a condition?
&lt;/h2&gt;

&lt;p&gt;React does not pass hooks a name or a key. It relies purely on call order. On every render, the first &lt;code&gt;useState&lt;/code&gt; it sees maps to the first state slot, the second to the second, and so on. If a hook call is behind an &lt;code&gt;if&lt;/code&gt;, the order changes between renders, and now &lt;code&gt;useState&lt;/code&gt; number 2 is reading the slot that belonged to a &lt;code&gt;useEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is the whole reason for the rules of hooks. It is not style, it is that the mechanism has no other way to line up "this call" with "that piece of state." Once people see it as an array indexed by call count, the lint rule stops feeling arbitrary.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Here is a component wrapped in &lt;code&gt;React.memo&lt;/code&gt; that still re-renders every time. Why?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; does a shallow compare of props. If the parent passes an object or array or function literal as a prop, that literal is a brand new reference on every render, so the shallow compare always says "different," and memo does nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;onClick&lt;/code&gt; are recreated each render. To make the memo actually hold you have to stabilise those references with &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt;, or lift the object out of the component if it never changes, or restructure so the child does not need them. A lot of "I added memo and nothing got faster" reports are exactly this.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Will an error boundary catch an error thrown in an &lt;code&gt;onClick&lt;/code&gt; handler?
&lt;/h2&gt;

&lt;p&gt;No. Error boundaries catch errors during rendering, in lifecycle methods, and in the constructors of the tree below them. They do not catch errors in event handlers, in async code, in &lt;code&gt;setTimeout&lt;/code&gt;, or in the boundary's own code. Event handlers run outside the render cycle, so React lets the error propagate to the normal browser error handling instead.&lt;/p&gt;

&lt;p&gt;If you want handler errors to show a fallback, you catch them yourself and put the failure into state, then render based on that state. Knowing this line matters because people wire up a boundary, test it by throwing in a click handler, see nothing happen, and conclude the boundary is broken.&lt;/p&gt;




&lt;p&gt;If your answer to any of these was "it's just best practice," that is usually the sign there is a mechanism underneath worth understanding. Happy to hear which ones you would swap out.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>interview</category>
    </item>
    <item>
      <title>useMemo and useCallback: 5 things that actually trip people up</title>
      <dc:creator>Tarun Sharma</dc:creator>
      <pubDate>Tue, 18 Aug 2026 12:47:54 +0000</pubDate>
      <link>https://dev.to/101beardo/usememo-and-usecallback-5-things-that-actually-trip-people-up-4o0l</link>
      <guid>https://dev.to/101beardo/usememo-and-usecallback-5-things-that-actually-trip-people-up-4o0l</guid>
      <description>&lt;p&gt;Both of these get memorized as syntax pretty fast. What doesn't get memorized is what they're actually doing under the hood, and that's where the bugs show up. Here's the stuff that actually trips people up once you go past "wrap it in useMemo I guess."&lt;/p&gt;

&lt;h2&gt;
  
  
  1. They solve different problems, not the same one
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; caches a value. &lt;code&gt;useCallback&lt;/code&gt; caches a function reference. People treat them like interchangeable "make it faster" hooks, but &lt;code&gt;useCallback(fn, deps)&lt;/code&gt; is really just &lt;code&gt;useMemo(() =&amp;gt; fn, deps)&lt;/code&gt; under the hood, it just hands you back the function itself instead of calling it for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Neither one makes your code faster by default
&lt;/h2&gt;

&lt;p&gt;Wrapping something in &lt;code&gt;useMemo&lt;/code&gt; has a cost too, it runs the dependency comparison on every render. If the calculation inside is cheap, you're paying more than you save. Reach for these when the calculation is genuinely expensive, or when the value needs to keep the same reference across renders (see #3), not as a reflex on every derived value.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The real reason you need useCallback: keeping props stable for React.memo
&lt;/h2&gt;

&lt;p&gt;If you pass a normal inline function as a prop to a memoized child, that child re-renders anyway, because the function is a new reference every single render. &lt;code&gt;useCallback&lt;/code&gt; is what actually keeps that reference stable across renders so &lt;code&gt;React.memo&lt;/code&gt;'s shallow comparison has something to bail out on. Without it, memo is comparing a new function to another new function every time and always finding them "different."&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The dependency array lies just as easily here as with useEffect
&lt;/h2&gt;

&lt;p&gt;Same stale closure trap you'd hit with &lt;code&gt;useEffect&lt;/code&gt;. If you memoize a function with &lt;code&gt;useCallback(fn, [])&lt;/code&gt; and &lt;code&gt;fn&lt;/code&gt; reads a prop or state value from outside, you get a function frozen with whatever that value was on the first render. The fix is the same one as always: put it in the deps array, don't fight the linter into silence.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Object and array literals as deps break memoization silently
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useMemo(() =&amp;gt; doSomething(config), [config])&lt;/code&gt; looks safe until &lt;code&gt;config&lt;/code&gt; is &lt;code&gt;{ foo: bar }&lt;/code&gt; created inline on every render, in which case the dependency is a new reference every time and the memo never actually hits, it recalculates every render while looking like it's working. Move the object outside the render, or memoize it too.&lt;/p&gt;

&lt;p&gt;Curious what the actual useMemo or useCallback bug was that got you. Drop it below, would love to hear it.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>interview</category>
    </item>
    <item>
      <title>5 React interview questions I'd actually ask (and how I'd answer them)</title>
      <dc:creator>Tarun Sharma</dc:creator>
      <pubDate>Fri, 14 Aug 2026 08:26:33 +0000</pubDate>
      <link>https://dev.to/101beardo/5-react-interview-questions-id-actually-ask-and-how-id-answer-them-3422</link>
      <guid>https://dev.to/101beardo/5-react-interview-questions-id-actually-ask-and-how-id-answer-them-3422</guid>
      <description>&lt;p&gt;Most "React interview questions" lists online are either trivia (define useEffect) or so advanced they're not useful below 3-4 years of experience. Here are 5 I think are actually worth knowing, with the answer I'd give if asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What does this log, and why?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&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 logs &lt;code&gt;3, 3, 3&lt;/code&gt;. &lt;code&gt;var&lt;/code&gt; gives the whole loop one shared variable, so by the time the callbacks run, the loop has already finished and &lt;code&gt;i&lt;/code&gt; is 3. Swap &lt;code&gt;var&lt;/code&gt; for &lt;code&gt;let&lt;/code&gt; and it logs &lt;code&gt;0, 1, 2&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt; creates a fresh binding for every iteration, so each callback closes over its own copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Why doesn't an empty dependency array guarantee no stale-closure bugs?
&lt;/h2&gt;

&lt;p&gt;An effect with &lt;code&gt;[]&lt;/code&gt; only runs once, but any function or state it references from the render it was created in is frozen at that value forever, that's a stale closure. It's the same mechanism as question 1, just applied to a React render instead of a loop iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. What's the actual difference between useMemo and useCallback?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useCallback(fn, deps)&lt;/code&gt; is just &lt;code&gt;useMemo(() =&amp;gt; fn, deps)&lt;/code&gt;. One memoizes a value, the other memoizes a function reference. People treat them as separate concepts when one is a special case of the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Why can a sibling component re-render even though its own props didn't change?
&lt;/h2&gt;

&lt;p&gt;Because React re-renders every child of a component that re-renders, by default, regardless of whether that specific child's props changed. &lt;code&gt;React.memo&lt;/code&gt; is what actually stops it, re-rendering isn't opt-out at the parent level, it's opt-in per child.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. What does the virtual DOM actually skip?
&lt;/h2&gt;

&lt;p&gt;It skips DOM writes, not DOM reads or re-renders. React still runs your component function and builds a new tree every render; the virtual DOM diff is what decides which actual DOM mutations are necessary, which are usually the expensive part.&lt;/p&gt;

&lt;p&gt;What would you add to this list?&lt;/p&gt;

</description>
      <category>interview</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
