<p dir="auto">In strict mode, React will call render method twice, to catch mutate-during-render type of bugs. However, there is an inconsistency in the way this is done for <code class="notranslate">useRef()</code>.</p>
<p dir="auto">During the <em>first</em> render only, each call will give you a fresh ref object. During subsequent calls, you will be given the same object during both calls.</p>
<p dir="auto">React version: 17.0.2</p>
<h2 dir="auto">Steps To Reproduce</h2>
<p dir="auto">Here is a little app to demo this.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import React from &quot;react&quot;;
import &quot;./styles.css&quot;;

const Hooky = () =&gt; {
  const ref = React.useRef(null);
  const [num, setNum] = React.useState(0);

  ref.current = (ref.current || 0) + 1;

  return (
    &lt;div&gt;
      &lt;p&gt;
        Val: {num} &lt;br /&gt;
        &lt;button onClick={() =&gt; setNum(Math.random())}&gt;Roll&lt;/button&gt;
      &lt;/p&gt;
      &lt;p&gt;Ref count: {ref.current}&lt;/p&gt;
    &lt;/div&gt;
  );
};

const App = () =&gt; {
  const [show, setShow] = React.useState(false);

  return (
    &lt;div&gt;
      &lt;h2&gt;Show or hide&lt;/h2&gt;
      &lt;button onClick={() =&gt; setShow(!show)}&gt;{show ? &quot;Hide&quot; : &quot;Show&quot;}&lt;/button&gt;
      &lt;hr /&gt;
      {show &amp;&amp; &lt;Hooky /&gt;}
    &lt;/div&gt;
  );
};

export default App;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-v">React</span> <span class="pl-k">from</span> <span class="pl-s">"react"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-s">"./styles.css"</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">Hooky</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">ref</span> <span class="pl-c1">=</span> <span class="pl-v">React</span><span class="pl-kos">.</span><span class="pl-en">useRef</span><span class="pl-kos">(</span><span class="pl-c1">null</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">const</span> <span class="pl-kos">[</span><span class="pl-s1">num</span><span class="pl-kos">,</span> <span class="pl-s1">setNum</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-v">React</span><span class="pl-kos">.</span><span class="pl-en">useState</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-s1">ref</span><span class="pl-kos">.</span><span class="pl-c1">current</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">ref</span><span class="pl-kos">.</span><span class="pl-c1">current</span> <span class="pl-c1">||</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span><span class="pl-kos">;</span>

  <span class="pl-k">return</span> <span class="pl-kos">(</span>
    <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">p</span><span class="pl-c1">&gt;</span>
        Val: <span class="pl-kos">{</span><span class="pl-s1">num</span><span class="pl-kos">}</span> <span class="pl-c1">&lt;</span><span class="pl-ent">br</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span>
        <span class="pl-c1">&lt;</span><span class="pl-ent">button</span> <span class="pl-c1">onClick</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">setNum</span><span class="pl-kos">(</span><span class="pl-v">Math</span><span class="pl-kos">.</span><span class="pl-en">random</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span>Roll<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">button</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">p</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">p</span><span class="pl-c1">&gt;</span>Ref count: <span class="pl-kos">{</span><span class="pl-s1">ref</span><span class="pl-kos">.</span><span class="pl-c1">current</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">p</span><span class="pl-c1">&gt;</span>
    <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
  <span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-v">App</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-kos">[</span><span class="pl-s1">show</span><span class="pl-kos">,</span> <span class="pl-s1">setShow</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-v">React</span><span class="pl-kos">.</span><span class="pl-en">useState</span><span class="pl-kos">(</span><span class="pl-c1">false</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-k">return</span> <span class="pl-kos">(</span>
    <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">h2</span><span class="pl-c1">&gt;</span>Show or hide<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">h2</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">button</span> <span class="pl-c1">onClick</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">setShow</span><span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-s1">show</span><span class="pl-kos">)</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">show</span> ? <span class="pl-s">"Hide"</span> : <span class="pl-s">"Show"</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">button</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">hr</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span>
      <span class="pl-kos">{</span><span class="pl-s1">show</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-c1">&lt;</span><span class="pl-v">Hooky</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span><span class="pl-kos">}</span>
    <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
  <span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-v">App</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Click "Show". You will see ref count set to <code class="notranslate">1</code>, indicating the <code class="notranslate">useRef</code> has returned a different object both times it was called (it could also mean the component was called only once, but that isn't the case, I checked using debugger). If you force rerender by clicking the other button, the ref will increase in increments of 2, which is what you'd expect.</p>
<p dir="auto">Link to code example: <a href="https://codesandbox.io/s/react-fiddle-forked-fkocg?file=/src/App.js" rel="nofollow">https://codesandbox.io/s/react-fiddle-forked-fkocg?file=/src/App.js</a></p>
<h2 dir="auto">The current behavior</h2>
<p dir="auto"><code class="notranslate">useRef</code> in strict mode has one behavior during first render and other during subsequent renders.</p>
<h2 dir="auto">The expected behavior</h2>
<p dir="auto"><code class="notranslate">useRef</code> operates consistently during all renders. Either always gives you the same object, or has a separate object for each "lane" and always reuses the same one.</p>
<p dir="auto">Basically, the counter in the code sandbox example should either go: <code class="notranslate">2 4 6 8</code> or <code class="notranslate">1 2 3 4</code>. Not <code class="notranslate">1 3 5 7</code>, as it does now.</p>
<h2 dir="auto">Why this matters</h2>
<p dir="auto">Practical issue where I encountered this was trying to do subscribe/unsubscribe system using refs. I want my components to consistently subscribe and subscribe callbacks, kind of like element ref works. This failed when I detected callbacks not getting called, due to a duplicate ref object provided the first time component is rendered.</p>
<p dir="auto"><a href="https://facebook.github.io/react/docs/perf.html" rel="nofollow">https://facebook.github.io/react/docs/perf.html</a></p>
<p dir="auto">IMO this is insufficient. Where are we supposed to place each of the API calls? Some example code would be great.</p>