<p dir="auto">When using the <code class="notranslate">setState</code> function from the state hook to update state based on prop changes like mentioned <a href="https://beta.reactjs.org/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state" rel="nofollow">here</a>, if <code class="notranslate">setState</code> is called with the same value as the current state (or a callback that returns the same value as the current state), React still re-renders the component unlike its behavior when <code class="notranslate">setState</code> is called outside a render.<br>
Is this intended behavior? If so, I think it might be helpful to put this in the docs somewhere around here <a href="https://beta.reactjs.org/reference/react/useState#setstate-caveats" rel="nofollow">https://beta.reactjs.org/reference/react/useState#setstate-caveats</a>?</p>
<p dir="auto">React version: 18.1.0</p>
<h2 dir="auto">Steps To Reproduce</h2>
<p dir="auto">The specific pattern that I was trying to use was something like this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function MyComponent() {
  const [state, setState] = useState(0);

  // referentially stable callback that might be used as a prop to a child
  const updateStateIfNeeded = useCallback((newState) =&gt; {
    setState(currentState =&gt; newState == currentState ? currentState : newState);
  }, []);

  // Infinite re-renders
  updateStateIfNeeded(newState);
  // I would need to duplicate the bit inside updateStateIfNeeded that checks against
  // currentState here to guard the setState call to avoid re-renders
  if (newState !== state) { setState(newState) }

  // Only re-renders when state is changed
  useEffect(() =&gt; updateStateIfNeeded(newState));

  return (...);
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">MyComponent</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-kos">[</span><span class="pl-s1">state</span><span class="pl-kos">,</span> <span class="pl-s1">setState</span><span class="pl-kos">]</span> <span class="pl-c1">=</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-c">// referentially stable callback that might be used as a prop to a child</span>
  <span class="pl-k">const</span> <span class="pl-s1">updateStateIfNeeded</span> <span class="pl-c1">=</span> <span class="pl-en">useCallback</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">newState</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-s1">setState</span><span class="pl-kos">(</span><span class="pl-s1">currentState</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">newState</span> <span class="pl-c1">==</span> <span class="pl-s1">currentState</span> ? <span class="pl-s1">currentState</span> : <span class="pl-s1">newState</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// Infinite re-renders</span>
  <span class="pl-s1">updateStateIfNeeded</span><span class="pl-kos">(</span><span class="pl-s1">newState</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-c">// I would need to duplicate the bit inside updateStateIfNeeded that checks against</span>
  <span class="pl-c">// currentState here to guard the setState call to avoid re-renders</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">newState</span> <span class="pl-c1">!==</span> <span class="pl-s1">state</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-s1">setState</span><span class="pl-kos">(</span><span class="pl-s1">newState</span><span class="pl-kos">)</span> <span class="pl-kos">}</span>

  <span class="pl-c">// Only re-renders when state is changed</span>
  <span class="pl-en">useEffect</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">updateStateIfNeeded</span><span class="pl-kos">(</span><span class="pl-s1">newState</span><span class="pl-kos">)</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-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">As per <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="46840299" data-permission-text="Title is private" data-url="https://github.com/facebook/react/issues/2410" data-hovercard-type="issue" data-hovercard-url="/facebook/react/issues/2410/hovercard?comment_id=115659185&amp;comment_type=issue_comment" href="https://github.com/facebook/react/issues/2410#issuecomment-115659185">#2410 (comment)</a>: findDOMNode(this) throws for unmounted components, but the error message is too cryptic:</p>
<p dir="auto"><code class="notranslate">Uncaught Error: Invariant Violation: Component (with keys: getDOMNode,_handleChange,props,context,state,refs,_reactInternalInstance) contains render method but is not mounted in the DOM</code></p>
<p dir="auto">Some expert React users honestly thought they had duplicate React or something, so didn't even bother to check whether the component was mounted. (It wasn't.)</p>