<p dir="auto"><strong>Do you want to request a <em>feature</em> or report a <em>bug</em>?</strong></p>
<p dir="auto">I want to report a bug</p>
<p dir="auto"><strong>What is the current behavior?</strong></p>
<p dir="auto">eslint --fix trying to break my hook)</p>
<p dir="auto"><strong>If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (<a href="https://jsfiddle.net/Luktwrdm/" rel="nofollow">https://jsfiddle.net/Luktwrdm/</a>) or CodeSandbox (<a href="https://codesandbox.io/s/new" rel="nofollow">https://codesandbox.io/s/new</a>) example below:</strong></p>
<p dir="auto">I have a very simple hook:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import { useEffect, useState } from 'react'

export function useSwitchTab(trigger, tabsAmount, initialState = 0) {
  const [currentTab, setTab] = useState(initialState - 1)

  useEffect(() =&gt; {
    setTab(currentTab + 1 &gt;= tabsAmount ? 0 : currentTab + 1)
  }, [tabsAmount, trigger])

  return [currentTab, setTab]
}"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">useEffect</span><span class="pl-kos">,</span> <span class="pl-s1">useState</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'react'</span>

<span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-en">useSwitchTab</span><span class="pl-kos">(</span><span class="pl-s1">trigger</span><span class="pl-kos">,</span> <span class="pl-s1">tabsAmount</span><span class="pl-kos">,</span> <span class="pl-s1">initialState</span> <span class="pl-c1">=</span> <span class="pl-c1">0</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">currentTab</span><span class="pl-kos">,</span> <span class="pl-s1">setTab</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-s1">initialState</span> <span class="pl-c1">-</span> <span class="pl-c1">1</span><span class="pl-kos">)</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-kos">{</span>
    <span class="pl-s1">setTab</span><span class="pl-kos">(</span><span class="pl-s1">currentTab</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span> <span class="pl-c1">&gt;=</span> <span class="pl-s1">tabsAmount</span> ? <span class="pl-c1">0</span> : <span class="pl-s1">currentTab</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s1">tabsAmount</span><span class="pl-kos">,</span> <span class="pl-s1">trigger</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-s1">currentTab</span><span class="pl-kos">,</span> <span class="pl-s1">setTab</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">If props <code class="notranslate">tabsAmount</code> or <code class="notranslate">trigger</code> will change, I need to increase <code class="notranslate">currentTab</code> value by 1. It works fine and looks ok for me, but in <code class="notranslate">eslint-plugin-react-hook</code> rule <code class="notranslate">react-hooks/exhaustive-deps</code> will warn here:</p>
<blockquote>
<p dir="auto">React Hook useEffect has a missing dependency: 'currentTab'. Either include it or remove the dependency array. You can also do a functional update 'setTab(c =&gt; ...)' if you only need 'c<br>
urrentTab' in the 'setTab' call  react-hooks/exhaustive-deps</p>
</blockquote>
<p dir="auto">And eslint --fix will break my code like this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import { useEffect, useState } from 'react'

export function useSwitchTab(trigger, tabsAmount, initialState = 0) {
  const [currentTab, setTab] = useState(initialState - 1)

  useEffect(() =&gt; {
    setTab(currentTab + 1 &gt;= tabsAmount ? 0 : currentTab + 1)
  }, [currentTab, tabsAmount, trigger])

  return [currentTab, setTab]
}"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">useEffect</span><span class="pl-kos">,</span> <span class="pl-s1">useState</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'react'</span>

<span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-en">useSwitchTab</span><span class="pl-kos">(</span><span class="pl-s1">trigger</span><span class="pl-kos">,</span> <span class="pl-s1">tabsAmount</span><span class="pl-kos">,</span> <span class="pl-s1">initialState</span> <span class="pl-c1">=</span> <span class="pl-c1">0</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">currentTab</span><span class="pl-kos">,</span> <span class="pl-s1">setTab</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-s1">initialState</span> <span class="pl-c1">-</span> <span class="pl-c1">1</span><span class="pl-kos">)</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-kos">{</span>
    <span class="pl-s1">setTab</span><span class="pl-kos">(</span><span class="pl-s1">currentTab</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span> <span class="pl-c1">&gt;=</span> <span class="pl-s1">tabsAmount</span> ? <span class="pl-c1">0</span> : <span class="pl-s1">currentTab</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-s1">currentTab</span><span class="pl-kos">,</span> <span class="pl-s1">tabsAmount</span><span class="pl-kos">,</span> <span class="pl-s1">trigger</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-s1">currentTab</span><span class="pl-kos">,</span> <span class="pl-s1">setTab</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">It will add <code class="notranslate">currentTab</code> in deps for useEffect and this will create <strong>endless loop</strong>.</p>
<p dir="auto"><strong>What is the expected behavior?</strong></p>
<p dir="auto">Eslint shouldn't fix this warning with --fix option, It may break the code.</p>
<p dir="auto"><strong>Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?</strong></p>
<p dir="auto">react: 16.8.5<br>
eslint-plugin-react-hooks: 1.6.0</p>
<p dir="auto"><strong>Do you want to request a <em>feature</em> or report a <em>bug</em>?</strong><br>
Bug</p>
<p dir="auto"><strong>What is the current behavior?</strong><br>
Consider:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function Example({ fetchData, someArg }) {
  let data = 'defaultValue';
  useEffect(() =&gt; {
    data = fetchData(someArg);
 }, [someArg]);

  return JSON.stringify(data);
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">Example</span><span class="pl-kos">(</span><span class="pl-kos">{</span> fetchData<span class="pl-kos">,</span> someArg <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">let</span> <span class="pl-s1">data</span> <span class="pl-c1">=</span> <span class="pl-s">'defaultValue'</span><span class="pl-kos">;</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-kos">{</span>
    <span class="pl-s1">data</span> <span class="pl-c1">=</span> <span class="pl-en">fetchData</span><span class="pl-kos">(</span><span class="pl-s1">someArg</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-s1">someArg</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-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">data</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">auto fix will automatically change this to:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function Example({ fetchData, someArg }) {
  let data = 'defaultValue';
  useEffect(() =&gt; {
    data = fetchData(someArg);
 }, [someArg, fetchData]);

  return JSON.stringify(data);
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">Example</span><span class="pl-kos">(</span><span class="pl-kos">{</span> fetchData<span class="pl-kos">,</span> someArg <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">let</span> <span class="pl-s1">data</span> <span class="pl-c1">=</span> <span class="pl-s">'defaultValue'</span><span class="pl-kos">;</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-kos">{</span>
    <span class="pl-s1">data</span> <span class="pl-c1">=</span> <span class="pl-en">fetchData</span><span class="pl-kos">(</span><span class="pl-s1">someArg</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-s1">someArg</span><span class="pl-kos">,</span> <span class="pl-s1">fetchData</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-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">data</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Here we have a simple data fetch component that should refetch data when parameters change, but not when the fetch function changes.  Whether this is right or not, it is legitimate code, that the lint fix will cause serious problems in the code if it is used like this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function ExmapleUsage({ fetchData }) {
  return &lt;Example fetchData={( arg ) =&gt; fetchData('Hello World', arg)} someArg=&quot;Goodbye&quot; /&gt; 
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-v">ExmapleUsage</span><span class="pl-kos">(</span><span class="pl-kos">{</span> fetchData <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-c1">&lt;</span><span class="pl-ent">Example</span> <span class="pl-c1">fetchData</span><span class="pl-c1">=</span><span class="pl-kos">{</span><span class="pl-kos">(</span> <span class="pl-s1">arg</span> <span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">fetchData</span><span class="pl-kos">(</span><span class="pl-s">'Hello World'</span><span class="pl-kos">,</span> <span class="pl-s1">arg</span><span class="pl-kos">)</span><span class="pl-kos">}</span> <span class="pl-c1">someArg</span><span class="pl-c1">=</span><span class="pl-s">"Goodbye"</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span> 
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>What is the expected behavior?</strong></p>
<p dir="auto"><a href="https://eslint.org/docs/developer-guide/working-with-rules#applying-fixes" rel="nofollow">Eslint best practices</a> say that fix rules should not change functionality of code, so that you can safely run fix and expect no functional changes to be made.  This rule directly breaks that.  I as a repo maintainer see the auto fix as a greater risk than the problems the lint rule prevents.  If autofix was turned off, the rule would be entirely a positive.<br>
Unfortunately, <a href="https://github.com/eslint/eslint/issues/7549" data-hovercard-type="issue" data-hovercard-url="/eslint/eslint/issues/7549/hovercard">ESLint also has rejected the idea of disabling autofix for certain rules</a>.  So not following best practices is not ideal.<br>
<strong>Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?</strong></p>
<p dir="auto">Not a React Bug but a lint rule.</p>