@@ -95,7 +95,7 @@ const tests = {
9595 const local1 = {};
9696 {
9797 const local2 = {};
98- useEffect (() => {
98+ useCallback (() => {
9999 console.log(local1);
100100 console.log(local2);
101101 }, [local1, local2]);
@@ -109,7 +109,7 @@ const tests = {
109109 const local1 = {};
110110 function MyNestedComponent() {
111111 const local2 = {};
112- useEffect (() => {
112+ useCallback (() => {
113113 console.log(local1);
114114 console.log(local2);
115115 }, [local2]);
@@ -590,6 +590,17 @@ const tests = {
590590 }
591591 ` ,
592592 } ,
593+ {
594+ // Valid even though activeTab is "unused".
595+ // We allow that in effects, but not callbacks or memo.
596+ code : `
597+ function Foo({ activeTab }) {
598+ useEffect(() => {
599+ window.scrollTo(0, 0);
600+ }, [activeTab]);
601+ }
602+ ` ,
603+ } ,
593604 ] ,
594605 invalid : [
595606 {
@@ -809,7 +820,7 @@ const tests = {
809820 function MyComponent() {
810821 const local1 = {};
811822 const local2 = {};
812- useEffect (() => {
823+ useMemo (() => {
813824 console.log(local1);
814825 }, [local1, local2]);
815826 }
@@ -818,13 +829,13 @@ const tests = {
818829 function MyComponent() {
819830 const local1 = {};
820831 const local2 = {};
821- useEffect (() => {
832+ useMemo (() => {
822833 console.log(local1);
823834 }, [local1]);
824835 }
825836 ` ,
826837 errors : [
827- "React Hook useEffect has an unnecessary dependency: 'local2'. " +
838+ "React Hook useMemo has an unnecessary dependency: 'local2'. " +
828839 'Either exclude it or remove the dependency array.' ,
829840 ] ,
830841 } ,
@@ -836,7 +847,7 @@ const tests = {
836847 const local1 = {};
837848 function MyNestedComponent() {
838849 const local2 = {};
839- useEffect (() => {
850+ useCallback (() => {
840851 console.log(local1);
841852 console.log(local2);
842853 }, [local1]);
@@ -848,7 +859,7 @@ const tests = {
848859 const local1 = {};
849860 function MyNestedComponent() {
850861 const local2 = {};
851- useEffect (() => {
862+ useCallback (() => {
852863 console.log(local1);
853864 console.log(local2);
854865 }, [local2]);
@@ -857,7 +868,7 @@ const tests = {
857868 ` ,
858869 errors : [
859870 // Focus on the more important part first (missing dep)
860- "React Hook useEffect has a missing dependency: 'local2'. " +
871+ "React Hook useCallback has a missing dependency: 'local2'. " +
861872 'Either include it or remove the dependency array.' ,
862873 ] ,
863874 } ,
@@ -912,16 +923,16 @@ const tests = {
912923 {
913924 code : `
914925 function MyComponent() {
915- useEffect (() => {}, [local]);
926+ useCallback (() => {}, [local]);
916927 }
917928 ` ,
918929 output : `
919930 function MyComponent() {
920- useEffect (() => {}, []);
931+ useCallback (() => {}, []);
921932 }
922933 ` ,
923934 errors : [
924- "React Hook useEffect has an unnecessary dependency: 'local'. " +
935+ "React Hook useCallback has an unnecessary dependency: 'local'. " +
925936 'Either exclude it or remove the dependency array.' ,
926937 ] ,
927938 } ,
@@ -1229,7 +1240,6 @@ const tests = {
12291240 ] ,
12301241 } ,
12311242 {
1232- // TODO: need to think more about this case.
12331243 code : `
12341244 function MyComponent() {
12351245 const local = {id: 42};
@@ -1238,13 +1248,14 @@ const tests = {
12381248 }, [local.id]);
12391249 }
12401250 ` ,
1241- // TODO: this may not be a good idea.
1251+ // TODO: autofix should be smart enough
1252+ // to remove local.id from the list.
12421253 output : `
12431254 function MyComponent() {
12441255 const local = {id: 42};
12451256 useEffect(() => {
12461257 console.log(local);
1247- }, [local]);
1258+ }, [local, local.id ]);
12481259 }
12491260 ` ,
12501261 errors : [
@@ -1278,7 +1289,7 @@ const tests = {
12781289 code : `
12791290 function MyComponent() {
12801291 const local1 = {};
1281- useEffect (() => {
1292+ useCallback (() => {
12821293 const local1 = {};
12831294 console.log(local1);
12841295 }, [local1]);
@@ -1287,32 +1298,32 @@ const tests = {
12871298 output : `
12881299 function MyComponent() {
12891300 const local1 = {};
1290- useEffect (() => {
1301+ useCallback (() => {
12911302 const local1 = {};
12921303 console.log(local1);
12931304 }, []);
12941305 }
12951306 ` ,
12961307 errors : [
1297- "React Hook useEffect has an unnecessary dependency: 'local1'. " +
1308+ "React Hook useCallback has an unnecessary dependency: 'local1'. " +
12981309 'Either exclude it or remove the dependency array.' ,
12991310 ] ,
13001311 } ,
13011312 {
13021313 code : `
13031314 function MyComponent() {
13041315 const local1 = {};
1305- useEffect (() => {}, [local1]);
1316+ useCallback (() => {}, [local1]);
13061317 }
13071318 ` ,
13081319 output : `
13091320 function MyComponent() {
13101321 const local1 = {};
1311- useEffect (() => {}, []);
1322+ useCallback (() => {}, []);
13121323 }
13131324 ` ,
13141325 errors : [
1315- "React Hook useEffect has an unnecessary dependency: 'local1'. " +
1326+ "React Hook useCallback has an unnecessary dependency: 'local1'. " +
13161327 'Either exclude it or remove the dependency array.' ,
13171328 ] ,
13181329 } ,
@@ -1785,6 +1796,62 @@ const tests = {
17851796 "because their mutation doesn't re-render the component." ,
17861797 ] ,
17871798 } ,
1799+ {
1800+ code : `
1801+ function MyComponent({ activeTab }) {
1802+ const ref1 = useRef();
1803+ const ref2 = useRef();
1804+ useEffect(() => {
1805+ ref1.current.scrollTop = 0;
1806+ ref2.current.scrollTop = 0;
1807+ }, [ref1.current, ref2.current, activeTab]);
1808+ }
1809+ ` ,
1810+ output : `
1811+ function MyComponent({ activeTab }) {
1812+ const ref1 = useRef();
1813+ const ref2 = useRef();
1814+ useEffect(() => {
1815+ ref1.current.scrollTop = 0;
1816+ ref2.current.scrollTop = 0;
1817+ }, [activeTab]);
1818+ }
1819+ ` ,
1820+ errors : [
1821+ "React Hook useEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " +
1822+ 'Either exclude them or remove the dependency array. ' +
1823+ "Mutable values like 'ref1.current' aren't valid dependencies " +
1824+ "because their mutation doesn't re-render the component." ,
1825+ ] ,
1826+ } ,
1827+ {
1828+ code : `
1829+ function MyComponent({ activeTab, initY }) {
1830+ const ref1 = useRef();
1831+ const ref2 = useRef();
1832+ const fn = useCallback(() => {
1833+ ref1.current.scrollTop = initY;
1834+ ref2.current.scrollTop = initY;
1835+ }, [ref1.current, ref2.current, activeTab, initY]);
1836+ }
1837+ ` ,
1838+ output : `
1839+ function MyComponent({ activeTab, initY }) {
1840+ const ref1 = useRef();
1841+ const ref2 = useRef();
1842+ const fn = useCallback(() => {
1843+ ref1.current.scrollTop = initY;
1844+ ref2.current.scrollTop = initY;
1845+ }, [initY]);
1846+ }
1847+ ` ,
1848+ errors : [
1849+ "React Hook useCallback has unnecessary dependencies: 'activeTab', 'ref1.current', and 'ref2.current'. " +
1850+ 'Either exclude them or remove the dependency array. ' +
1851+ "Mutable values like 'ref1.current' aren't valid dependencies " +
1852+ "because their mutation doesn't re-render the component." ,
1853+ ] ,
1854+ } ,
17881855 {
17891856 code : `
17901857 function MyComponent() {
0 commit comments