eslint-plugin-react-hooks
Advanced tools
Comparing version 4.3.0 to 4.6.0
@@ -1,2 +0,3 @@ | ||
/** @license React vundefined | ||
/** | ||
* @license React | ||
* eslint-plugin-react-hooks.production.min.js | ||
@@ -30,34 +31,34 @@ * | ||
exports.rules={"rules-of-hooks":{meta:{type:"problem",docs:{description:"enforces the Rules of Hooks",recommended:!0,url:"https://reactjs.org/docs/hooks-rules.html"}},create:function(a){var c=[],b=[];return{onCodePathSegmentStart:function(a){return b.push(a)},onCodePathSegmentEnd:function(){return b.pop()},onCodePathStart:function(){return c.push(new Map)},onCodePathEnd:function(b,f){function d(a,c){var e=d.cache,f=e.get(a.id);c=new Set(c);if(c.has(a.id)){e=[].concat(c);a=e.slice(e.indexOf(a.id)+ | ||
1);a=D(a);var l;try{for(a.s();!(l=a.n()).done;)E.add(l.value)}catch(u){a.e(u)}finally{a.f()}return 0}c.add(a.id);if(void 0!==f)return f;if(b.thrownSegments.includes(a))f=0;else if(0===a.prevSegments.length)f=1;else{f=0;l=D(a.prevSegments);var r;try{for(l.s();!(r=l.n()).done;)f+=d(r.value,c)}catch(u){l.e(u)}finally{l.f()}}a.reachable&&0===f?e.delete(a.id):e.set(a.id,f);return f}function g(a,c){var d=g.cache,e=d.get(a.id);c=new Set(c);if(c.has(a.id)){d=Array.from(c);a=d.slice(d.indexOf(a.id)+1);a=D(a); | ||
var f;try{for(a.s();!(f=a.n()).done;)E.add(f.value)}catch(u){a.e(u)}finally{a.f()}return 0}c.add(a.id);if(void 0!==e)return e;if(b.thrownSegments.includes(a))e=0;else if(0===a.nextSegments.length)e=1;else{e=0;f=D(a.nextSegments);var r;try{for(f.s();!(r=f.n()).done;)e+=g(r.value,c)}catch(u){f.e(u)}finally{f.f()}}d.set(a.id,e);return e}function w(a){var c=w.cache,b=c.get(a.id);if(null===b)return Infinity;if(void 0!==b)return b;c.set(a.id,null);if(0===a.prevSegments.length)b=1;else{b=Infinity;var d= | ||
D(a.prevSegments),e;try{for(d.s();!(e=d.n()).done;){var f=w(e.value);f<b&&(b=f)}}catch(u){d.e(u)}finally{d.f()}b+=1}c.set(a.id,b);return b}var m=c.pop();if(0!==m.size){var E=new Set;d.cache=new Map;g.cache=new Map;w.cache=new Map;var x=g(b.initialSegment),r=na(f),e=ma(f),C=r?ea(r)||G(r):ha(f)||ia(f),t=Infinity,h=D(b.finalSegments),ja;try{for(h.s();!(ja=h.n()).done;){var ka=ja.value;if(ka.reachable){var la=w(ka);la<t&&(t=la)}}}catch(l){h.e(l)}finally{h.f()}m=D(m);var A;try{for(m.s();!(A=m.n()).done;){var F= | ||
A.value,q=F[0],B=F[1];if(q.reachable){var N=0===q.nextSegments.length?t<=w(q):t<w(q),T=d(q)*g(q),U=E.has(q.id),J=D(B),y;try{for(J.s();!(y=J.n()).done;){var z=y.value;U&&a.report({node:z,message:'React Hook "'+a.getSource(z)+'" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.'});if(C){if(!U&&T!==x){var O='React Hook "'+a.getSource(z)+'" is called conditionally. React Hooks must be called in the exact same order in every component render.'+ | ||
(N?" Did you accidentally call a React Hook after an early return?":"");a.report({node:z,message:O})}}else if(f.parent&&("MethodDefinition"===f.parent.type||"ClassProperty"===f.parent.type)&&f.parent.value===f){var M='React Hook "'+a.getSource(z)+'" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function.';a.report({node:z,message:M})}else if(r){var K='React Hook "'+a.getSource(z)+'" is called in function "'+(a.getSource(r)+'" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".'); | ||
a.report({node:z,message:K})}else if("Program"===f.type){var L='React Hook "'+a.getSource(z)+'" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function.';a.report({node:z,message:L})}else if(e){var n='React Hook "'+a.getSource(z)+'" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.';a.report({node:z,message:n})}}}catch(l){J.e(l)}finally{J.f()}}}}catch(l){m.e(l)}finally{m.f()}}}, | ||
CallExpression:function(a){if(G(a.callee)){var d=c[c.length-1],p=b[b.length-1],g=d.get(p);g||(g=[],d.set(p,g));g.push(a.callee)}}}}},"exhaustive-deps":{meta:{type:"suggestion",docs:{description:"verifies the list of dependencies for Hooks like useEffect and similar",recommended:!0,url:"https://github.com/facebook/react/issues/14920"},fixable:"code",hasSuggestions:!0,schema:[{type:"object",additionalProperties:!1,enableDangerousAutofixThisMayCauseInfiniteLoops:!1,properties:{additionalHooks:{type:"string"}, | ||
enableDangerousAutofixThisMayCauseInfiniteLoops:{type:"boolean"}}}]},create:function(a){function c(c){f&&Array.isArray(c.suggest)&&0<c.suggest.length&&(c.fix=c.suggest[0].fix);a.report(c)}function b(a,c){return function(b){if(c.has(b))return c.get(b);var d=a(b);c.set(b,d);return d}}function d(d,e,f,t,h){function r(a){var c=D(a.references),b;try{for(c.s();!(b=c.n()).done;){var k=b.value;if(k.resolved&&F.has(k.resolved.scope)){var f=Y(d,k.identifier),e=sa(f),g=X(e,z),t;if(t=h&&"Identifier"===e.type&& | ||
("MemberExpression"===e.parent.type||"OptionalMemberExpression"===e.parent.type)&&!e.parent.computed&&"Identifier"===e.parent.property.type&&"current"===e.parent.property.name){for(var l=k.from,n=!1;l.block!==d;)"function"===l.type&&(n=null!=l.block.parent&&"ReturnStatement"===l.block.parent.type),l=l.upper;t=n}t&&J.set(g,{reference:k,dependencyNode:e});if("TSTypeQuery"!==e.parent.type&&"TSTypeReference"!==e.parent.type){var C=k.resolved.defs[0];if(null!=C&&(null==C.node||C.node.init!==d.parent)&& | ||
"TypeParameter"!==C.type)if(y.has(g))y.get(g).references.push(k);else{var p=k.resolved,q=T(p)||U(p);y.set(g,{isStable:q,references:[k]})}}}}}catch(aa){c.e(aa)}finally{c.f()}a=D(a.childScopes);var m;try{for(a.s();!(m=a.n()).done;)r(m.value)}catch(aa){a.e(aa)}finally{a.f()}}function C(a){a=a.split(".");for(var c="",b=0;b<a.length;b++){if(0!==b){var k=a.slice(0,b+1).join(".");k=!0===z.get(k);c+=k?"?.":"."}c+=a[b]}return c}function p(a,c,b,d){return 0===a.size?null:(1<a.size?"":c+" ")+b+" "+(1<a.size? | ||
"dependencies":"dependency")+": "+wa(Array.from(a).sort().map(function(a){return"'"+C(a)+"'"}))+(". Either "+d+" "+(1<a.size?"them":"it")+" or remove the dependency array.")}h&&d.async&&c({node:d,message:"Effect callbacks are synchronous to prevent race conditions. Put the async function inside:\n\nuseEffect(() => {\n async function fetchData() {\n // You can await here\n const response = await MyAPI.getData(someId);\n // ...\n }\n fetchData();\n}, [someId]); // Or [] if effect doesn't need props or state\n\nLearn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"}); | ||
1);a=D(a);var l;try{for(a.s();!(l=a.n()).done;)E.add(l.value)}catch(u){a.e(u)}finally{a.f()}return BigInt("0")}c.add(a.id);if(void 0!==f)return f;if(b.thrownSegments.includes(a))f=BigInt("0");else if(0===a.prevSegments.length)f=BigInt("1");else{f=BigInt("0");l=D(a.prevSegments);var r;try{for(l.s();!(r=l.n()).done;)f+=d(r.value,c)}catch(u){l.e(u)}finally{l.f()}}a.reachable&&f===BigInt("0")?e.delete(a.id):e.set(a.id,f);return f}function g(a,c){var d=g.cache,e=d.get(a.id);c=new Set(c);if(c.has(a.id)){d= | ||
Array.from(c);a=d.slice(d.indexOf(a.id)+1);a=D(a);var f;try{for(a.s();!(f=a.n()).done;)E.add(f.value)}catch(u){a.e(u)}finally{a.f()}return BigInt("0")}c.add(a.id);if(void 0!==e)return e;if(b.thrownSegments.includes(a))e=BigInt("0");else if(0===a.nextSegments.length)e=BigInt("1");else{e=BigInt("0");f=D(a.nextSegments);var r;try{for(f.s();!(r=f.n()).done;)e+=g(r.value,c)}catch(u){f.e(u)}finally{f.f()}}d.set(a.id,e);return e}function w(a){var c=w.cache,b=c.get(a.id);if(null===b)return Infinity;if(void 0!== | ||
b)return b;c.set(a.id,null);if(0===a.prevSegments.length)b=1;else{b=Infinity;var d=D(a.prevSegments),e;try{for(d.s();!(e=d.n()).done;){var f=w(e.value);f<b&&(b=f)}}catch(u){d.e(u)}finally{d.f()}b+=1}c.set(a.id,b);return b}var m=c.pop();if(0!==m.size){var E=new Set;d.cache=new Map;g.cache=new Map;w.cache=new Map;var x=g(b.initialSegment),r=na(f),e=ma(f),C=r?ea(r)||G(r):ha(f)||ia(f),t=Infinity,h=D(b.finalSegments),ja;try{for(h.s();!(ja=h.n()).done;){var ka=ja.value;if(ka.reachable){var la=w(ka);la< | ||
t&&(t=la)}}}catch(l){h.e(l)}finally{h.f()}m=D(m);var A;try{for(m.s();!(A=m.n()).done;){var F=A.value,q=F[0],B=F[1];if(q.reachable){var N=0===q.nextSegments.length?t<=w(q):t<w(q),T=d(q)*g(q),U=E.has(q.id),J=D(B),y;try{for(J.s();!(y=J.n()).done;){var z=y.value;U&&a.report({node:z,message:'React Hook "'+a.getSource(z)+'" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.'});if(C){if(!U&&T!==x){var O='React Hook "'+ | ||
a.getSource(z)+'" is called conditionally. React Hooks must be called in the exact same order in every component render.'+(N?" Did you accidentally call a React Hook after an early return?":"");a.report({node:z,message:O})}}else if(f.parent&&("MethodDefinition"===f.parent.type||"ClassProperty"===f.parent.type)&&f.parent.value===f){var M='React Hook "'+a.getSource(z)+'" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function.'; | ||
a.report({node:z,message:M})}else if(r){var K='React Hook "'+a.getSource(z)+'" is called in function "'+(a.getSource(r)+'" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".');a.report({node:z,message:K})}else if("Program"===f.type){var L='React Hook "'+a.getSource(z)+'" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function.'; | ||
a.report({node:z,message:L})}else if(e){var n='React Hook "'+a.getSource(z)+'" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.';a.report({node:z,message:n})}}}catch(l){J.e(l)}finally{J.f()}}}}catch(l){m.e(l)}finally{m.f()}}},CallExpression:function(a){if(G(a.callee)){var d=c[c.length-1],p=b[b.length-1],g=d.get(p);g||(g=[],d.set(p,g));g.push(a.callee)}}}}},"exhaustive-deps":{meta:{type:"suggestion",docs:{description:"verifies the list of dependencies for Hooks like useEffect and similar", | ||
recommended:!0,url:"https://github.com/facebook/react/issues/14920"},fixable:"code",hasSuggestions:!0,schema:[{type:"object",additionalProperties:!1,enableDangerousAutofixThisMayCauseInfiniteLoops:!1,properties:{additionalHooks:{type:"string"},enableDangerousAutofixThisMayCauseInfiniteLoops:{type:"boolean"}}}]},create:function(a){function c(c){f&&Array.isArray(c.suggest)&&0<c.suggest.length&&(c.fix=c.suggest[0].fix);a.report(c)}function b(a,c){return function(b){if(c.has(b))return c.get(b);var d= | ||
a(b);c.set(b,d);return d}}function d(d,e,f,t,h){function r(a){var c=D(a.references),b;try{for(c.s();!(b=c.n()).done;){var k=b.value;if(k.resolved&&F.has(k.resolved.scope)){var f=Y(d,k.identifier),e=sa(f),g=X(e,z),t;if(t=h&&"Identifier"===e.type&&("MemberExpression"===e.parent.type||"OptionalMemberExpression"===e.parent.type)&&!e.parent.computed&&"Identifier"===e.parent.property.type&&"current"===e.parent.property.name){for(var l=k.from,n=!1;l.block!==d;)"function"===l.type&&(n=null!=l.block.parent&& | ||
"ReturnStatement"===l.block.parent.type),l=l.upper;t=n}t&&J.set(g,{reference:k,dependencyNode:e});if("TSTypeQuery"!==e.parent.type&&"TSTypeReference"!==e.parent.type){var C=k.resolved.defs[0];if(null!=C&&(null==C.node||C.node.init!==d.parent)&&"TypeParameter"!==C.type)if(y.has(g))y.get(g).references.push(k);else{var p=k.resolved,q=T(p)||U(p);y.set(g,{isStable:q,references:[k]})}}}}}catch(aa){c.e(aa)}finally{c.f()}a=D(a.childScopes);var m;try{for(a.s();!(m=a.n()).done;)r(m.value)}catch(aa){a.e(aa)}finally{a.f()}} | ||
function C(a){a=a.split(".");for(var c="",b=0;b<a.length;b++){if(0!==b){var k=a.slice(0,b+1).join(".");k=!0===z.get(k);c+=k?"?.":"."}c+=a[b]}return c}function p(a,c,b,d){return 0===a.size?null:(1<a.size?"":c+" ")+b+" "+(1<a.size?"dependencies":"dependency")+": "+wa(Array.from(a).sort().map(function(a){return"'"+C(a)+"'"}))+(". Either "+d+" "+(1<a.size?"them":"it")+" or remove the dependency array.")}h&&d.async&&c({node:d,message:"Effect callbacks are synchronous to prevent race conditions. Put the async function inside:\n\nuseEffect(() => {\n async function fetchData() {\n // You can await here\n const response = await MyAPI.getData(someId);\n // ...\n }\n fetchData();\n}, [someId]); // Or [] if effect doesn't need props or state\n\nLearn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching"}); | ||
for(var A=g.acquire(d),F=new Set,q=null,B=A.upper;B;){F.add(B);if("function"===B.type)break;B=B.upper}if(B){q=B;var N=Array.isArray,T=b(function(a){if(!N(a.defs))return!1;var c=a.defs[0];if(null==c||"VariableDeclarator"!==c.node.type)return!1;var b=c.node.init;if(null==b)return!1;for(;"TSAsExpression"===b.type;)b=b.expression;var d=c.node.parent;if(null==d&&(Y(q.block,c.node.id),d=c.node.parent,null==d))return!1;if("const"===d.kind&&"Literal"===b.type&&("string"===typeof b.value||"number"===typeof b.value|| | ||
null===b.value))return!0;if("CallExpression"!==b.type)return!1;b=b.callee;"MemberExpression"!==b.type||"React"!==b.object.name||null==b.property||b.computed||(b=b.property);if("Identifier"!==b.type)return!1;c=c.node.id;b=b.name;if("useRef"===b&&"Identifier"===c.type)return!0;if("useState"===b||"useReducer"===b){if("ArrayPattern"===c.type&&2===c.elements.length&&N(a.identifiers)){if(c.elements[1]===a.identifiers[0]){if("useState"===b)for(a=a.references,b=0;b<a.length;b++)w.set(a[b].identifier,c.elements[0]); | ||
return!0}if(c.elements[0]===a.identifiers[0]&&"useState"===b)for(a=a.references,c=0;c<a.length;c++)m.add(a[c].identifier)}}else if("useTransition"===b&&"ArrayPattern"===c.type&&2===c.elements.length&&Array.isArray(a.identifiers)&&c.elements[1]===a.identifiers[0])return!0;return!1},E),U=b(function(a){if(!N(a.defs))return!1;a=a.defs[0];if(null==a||null==a.node||null==a.node.id)return!1;var c=a.node,b=q.childScopes;a=null;var d;for(d=0;d<b.length;d++){var e=b[d],k=e.block;if("FunctionDeclaration"=== | ||
c.type&&k===c||"VariableDeclarator"===c.type&&k.parent===c){a=e;break}}if(null==a)return!1;for(d=0;d<a.through.length;d++)if(c=a.through[d],null!=c.resolved&&F.has(c.resolved.scope)&&!T(c.resolved))return!1;return!0},x),J=new Map,y=new Map,z=new Map;r(A);J.forEach(function(a,b){var d=a.dependencyNode;a=a.reference.resolved.references;for(var e=!1,f=0;f<a.length;f++){var k=a[f].identifier.parent;if(null!=k&&"MemberExpression"===k.type&&!k.computed&&"Identifier"===k.property.type&&"current"===k.property.name&& | ||
"AssignmentExpression"===k.parent.type&&k.parent.left===k){e=!0;break}}e||c({node:d.parent.property,message:"The ref value '"+b+".current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy '"+(b+".current' to a variable inside the effect, and use that variable in the cleanup function.")})});var O=new Set,M=new Set;y.forEach(function(b,d){var e=b.references;b.isStable&&M.add(d);e.forEach(function(b){b.writeExpr&&(b=b.writeExpr, | ||
O.has(d)||(O.add(d),c({node:b,message:"Assignments to the '"+d+"' variable from inside React Hook "+(a.getSource(f)+" will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside ")+(a.getSource(f)+".")})))})});if(!(0<O.size))if(e){var K=[],L=new Set;"ArrayExpression"!==e.type?c({node:e,message:"React Hook "+a.getSource(f)+" was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies."}): | ||
e.elements.forEach(function(b){if(null!==b)if("SpreadElement"===b.type)c({node:b,message:"React Hook "+a.getSource(f)+" has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies."});else{try{var d=X(b,null)}catch(ra){if(/Unsupported node type/.test(ra.message)){"Literal"===b.type?y.has(b.value)?c({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. Did you mean to include "+(b.value+" in the array instead?")}): | ||
c({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. You can safely remove it."}):c({node:b,message:"React Hook "+a.getSource(f)+" has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked."});return}throw ra;}for(var e=b;"MemberExpression"===e.type||"OptionalMemberExpression"===e.type||"ChainExpression"===e.type;)e=e.object||e.expression.object;var k=!q.through.some(function(a){return a.identifier=== | ||
e});K.push({key:d,node:b});k||L.add(d)}});var n=H({dependencies:y,declaredDependencies:K,stableDependencies:M,externalDependencies:L,isEffect:h});B=n.unnecessaryDependencies;var l=n.missingDependencies,qa=n.duplicateDependencies,R=n.suggestedDependencies;if(0===qa.size+l.size+B.size)oa({declaredDependencies:K,declaredDependenciesNode:e,componentScope:q,scope:A}).forEach(function(a){var b=a.construction,d=a.isUsedOutsideOfHook;a=a.depType;var f="function"===a?"useCallback":"useMemo",k="function"=== | ||
a?"definition":"initialization",h="wrap the "+k+" of '"+b.name.name+"' in its own "+f+"() Hook.";h="The '"+b.name.name+"' "+a+" "+("conditional"===a||"logical expression"===a?"could make":"makes")+" the dependencies of "+(t+" Hook (at line "+e.loc.start.line+") change on every render. ")+(d?"To fix this, "+h:"Move it inside the "+t+" callback. Alternatively, "+h);var g;d&&"Variable"===b.type&&"function"===a&&(g=[{desc:"Wrap the "+k+" of '"+b.name.name+"' in its own "+f+"() Hook.",fix:function(a){var c= | ||
"useMemo"===f?["useMemo(() => { return ","; })"]:["useCallback(",")"],d=c[1];return[a.insertTextBefore(b.node.init,c[0]),a.insertTextAfter(b.node.init,d)]}}]);c({node:b.node,message:h,suggest:g})});else{!h&&0<l.size&&(R=H({dependencies:y,declaredDependencies:[],stableDependencies:M,externalDependencies:L,isEffect:h}).suggestedDependencies);(function(){if(0===K.length)return!0;var a=K.map(function(a){return a.key}),b=a.slice().sort();return a.join(",")===b.join(",")})()&&R.sort();n="";if(0<B.size){var S= | ||
null;Array.from(B.keys()).forEach(function(a){null===S&&a.endsWith(".current")&&(S=a)});if(null!==S)n=" Mutable values like '"+S+"' aren't valid dependencies because mutating them doesn't re-render the component.";else if(0<L.size){var I=Array.from(L)[0];A.set.has(I)||(n=" Outer scope values like '"+I+"' aren't valid dependencies because mutating them doesn't re-render the component.")}}if(!n&&l.has("props")){A=y.get("props");if(null==A)return;A=A.references;if(!Array.isArray(A))return;I=!0;for(var Z= | ||
0;Z<A.length;Z++){var u=Y(q.block,A[Z].identifier);if(!u){I=!1;break}u=u.parent;if(null==u){I=!1;break}if("MemberExpression"!==u.type&&"OptionalMemberExpression"!==u.type){I=!1;break}}I&&(n=" However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the "+(t+" call and refer to those specific props inside ")+(a.getSource(f)+"."))}if(!n&&0<l.size){var V=null;l.forEach(function(a){if(!V){var b=q.set.get(a),c=y.get(a);if(c.references[0].resolved=== | ||
b&&(b=b.defs[0],null!=b&&null!=b.name&&"Parameter"===b.type)){b=!1;for(var d,e=0;e<c.references.length;e++)if(d=c.references[e].identifier,null!=d&&null!=d.parent&&("CallExpression"===d.parent.type||"OptionalCallExpression"===d.parent.type)&&d.parent.callee===d){b=!0;break}b&&(V=a)}}});null!==V&&(n=" If '"+V+"' changes too often, find the parent component that defines it and wrap that definition in useCallback.")}if(!n&&0<l.size){var v=null;l.forEach(function(a){if(null===v)for(var b=y.get(a).references, | ||
c,d,e=0;e<b.length;e++){c=b[e].identifier;for(d=c.parent;null!=d&&d!==q.block;){if("CallExpression"===d.type){var f=w.get(d.callee);if(null!=f){f.name===a?v={missingDep:a,setter:d.callee.name,form:"updater"}:m.has(c)?v={missingDep:a,setter:d.callee.name,form:"reducer"}:(c=b[e].resolved,null!=c&&(c=c.defs[0],null!=c&&"Parameter"===c.type&&(v={missingDep:a,setter:d.callee.name,form:"inlineReducer"})));break}}d=d.parent}if(null!==v)break}});if(null!==v)switch(v.form){case "reducer":n=" You can also replace multiple useState variables with useReducer if '"+ | ||
(v.setter+"' needs the current value of '")+(v.missingDep+"'.");break;case "inlineReducer":n=" If '"+v.setter+"' needs the current value of '"+(v.missingDep+"', you can also switch to useReducer instead of useState and read '")+(v.missingDep+"' in the reducer.");break;case "updater":n=" You can also do a functional update '"+v.setter+"("+v.missingDep.substring(0,1)+" => ...)' if you only need '"+v.missingDep+"' in the '"+(v.setter+"' call.");break;default:throw Error("Unknown case.");}}c({node:e, | ||
message:"React Hook "+a.getSource(f)+" has "+(p(l,"a","missing","include")||p(B,"an","unnecessary","exclude")||p(qa,"a","duplicate","omit"))+n,suggest:[{desc:"Update the dependencies array to be: ["+R.map(C).join(", ")+"]",fix:function(a){return a.replaceText(e,"["+R.map(C).join(", ")+"]")}}]})}}else{var P=null;y.forEach(function(a,b){P||a.references.forEach(function(a){if(!P&&w.has(a.identifier)){for(a=a.from;"function"!==a.type;)a=a.upper;a.block===d&&(P=b)}})});if(P){var ba=H({dependencies:y,declaredDependencies:[], | ||
stableDependencies:M,externalDependencies:new Set,isEffect:!0}).suggestedDependencies;c({node:f,message:"React Hook "+t+" contains a call to '"+P+"'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass ["+ba.join(", ")+("] as a second argument to the "+t+" Hook."),suggest:[{desc:"Add dependencies array: ["+ba.join(", ")+"]",fix:function(a){return a.insertTextAfter(d,", ["+ba.join(", ")+"]")}}]})}}}}var f=a.options&&a.options[0]&&a.options[0].enableDangerousAutofixThisMayCauseInfiniteLoops|| | ||
!1,p={additionalHooks:a.options&&a.options[0]&&a.options[0].additionalHooks?new RegExp(a.options[0].additionalHooks):void 0,enableDangerousAutofixThisMayCauseInfiniteLoops:f},g=a.getSourceCode().scopeManager,w=new WeakMap,m=new WeakSet,E=new WeakMap,x=new WeakMap;return{CallExpression:function(b){var e=ua(b.callee,p);if(-1!==e){var f=b.arguments[e],g=b.callee,h=ta(g).name,m=b.arguments[e+1];b=/Effect($|[^a-z])/g.test(h);if(f)if(m||b){switch(f.type){case "FunctionExpression":case "ArrowFunctionExpression":d(f, | ||
m,g,h,b);return;case "Identifier":if(!m||m.elements&&m.elements.some(function(a){return a&&"Identifier"===a.type&&a.name===f.name}))return;e=a.getScope().set.get(f.name);if(null==e||null==e.defs)return;e=e.defs[0];if(!e||!e.node)break;if("Variable"!==e.type&&"FunctionName"!==e.type)break;switch(e.node.type){case "FunctionDeclaration":d(e.node,m,g,h,b);return;case "VariableDeclarator":if(e=e.node.init)switch(e.type){case "ArrowFunctionExpression":case "FunctionExpression":d(e,m,g,h,b);return}}break; | ||
default:c({node:g,message:"React Hook "+h+" received a function whose dependencies are unknown. Pass an inline function instead."});return}c({node:g,message:"React Hook "+h+" has a missing dependency: '"+f.name+"'. Either include it or remove the dependency array.",suggest:[{desc:"Update the dependencies array to be: ["+f.name+"]",fix:function(a){return a.replaceText(m,"["+f.name+"]")}}]})}else"useMemo"!==h&&"useCallback"!==h||c({node:g,message:"React Hook "+h+" does nothing when called with only one argument. Did you forget to pass an array of dependencies?"}); | ||
else c({node:g,message:"React Hook "+h+" requires an effect callback. Did you forget to pass a callback to the hook?"})}}}}}}; | ||
null===b.value))return!0;if("CallExpression"!==b.type)return!1;b=b.callee;"MemberExpression"!==b.type||"React"!==b.object.name||null==b.property||b.computed||(b=b.property);if("Identifier"!==b.type)return!1;c=c.node.id;b=b.name;if("useRef"===b&&"Identifier"===c.type)return!0;if("useState"===b||"useReducer"===b){if("ArrayPattern"===c.type&&2===c.elements.length&&N(a.identifiers)){if(c.elements[1]===a.identifiers[0]){if("useState"===b)for(a=a.references,d=b=0;d<a.length;d++){a[d].isWrite()&&b++;if(1< | ||
b)return!1;w.set(a[d].identifier,c.elements[0])}return!0}if(c.elements[0]===a.identifiers[0]&&"useState"===b)for(a=a.references,c=0;c<a.length;c++)m.add(a[c].identifier)}}else if("useTransition"===b&&"ArrayPattern"===c.type&&2===c.elements.length&&Array.isArray(a.identifiers)&&c.elements[1]===a.identifiers[0])return!0;return!1},E),U=b(function(a){if(!N(a.defs))return!1;a=a.defs[0];if(null==a||null==a.node||null==a.node.id)return!1;var c=a.node,b=q.childScopes;a=null;var d;for(d=0;d<b.length;d++){var e= | ||
b[d],k=e.block;if("FunctionDeclaration"===c.type&&k===c||"VariableDeclarator"===c.type&&k.parent===c){a=e;break}}if(null==a)return!1;for(d=0;d<a.through.length;d++)if(c=a.through[d],null!=c.resolved&&F.has(c.resolved.scope)&&!T(c.resolved))return!1;return!0},x),J=new Map,y=new Map,z=new Map;r(A);J.forEach(function(a,b){var d=a.dependencyNode;a=a.reference.resolved.references;for(var e=!1,f=0;f<a.length;f++){var k=a[f].identifier.parent;if(null!=k&&"MemberExpression"===k.type&&!k.computed&&"Identifier"=== | ||
k.property.type&&"current"===k.property.name&&"AssignmentExpression"===k.parent.type&&k.parent.left===k){e=!0;break}}e||c({node:d.parent.property,message:"The ref value '"+b+".current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy '"+(b+".current' to a variable inside the effect, and use that variable in the cleanup function.")})});var O=new Set,M=new Set;y.forEach(function(b,d){var e=b.references;b.isStable&&M.add(d); | ||
e.forEach(function(b){b.writeExpr&&(b=b.writeExpr,O.has(d)||(O.add(d),c({node:b,message:"Assignments to the '"+d+"' variable from inside React Hook "+(a.getSource(f)+" will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside ")+(a.getSource(f)+".")})))})});if(!(0<O.size))if(e){var K=[],L=new Set;"ArrayExpression"!==e.type?c({node:e,message:"React Hook "+a.getSource(f)+ | ||
" was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies."}):e.elements.forEach(function(b){if(null!==b)if("SpreadElement"===b.type)c({node:b,message:"React Hook "+a.getSource(f)+" has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies."});else{try{var d=X(b,null)}catch(ra){if(/Unsupported node type/.test(ra.message)){"Literal"===b.type? | ||
y.has(b.value)?c({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. Did you mean to include "+(b.value+" in the array instead?")}):c({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. You can safely remove it."}):c({node:b,message:"React Hook "+a.getSource(f)+" has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked."});return}throw ra;}for(var e=b;"MemberExpression"=== | ||
e.type||"OptionalMemberExpression"===e.type||"ChainExpression"===e.type;)e=e.object||e.expression.object;var k=!q.through.some(function(a){return a.identifier===e});K.push({key:d,node:b});k||L.add(d)}});var n=H({dependencies:y,declaredDependencies:K,stableDependencies:M,externalDependencies:L,isEffect:h});B=n.unnecessaryDependencies;var l=n.missingDependencies,qa=n.duplicateDependencies,R=n.suggestedDependencies;if(0===qa.size+l.size+B.size)oa({declaredDependencies:K,declaredDependenciesNode:e,componentScope:q, | ||
scope:A}).forEach(function(a){var b=a.construction,d=a.isUsedOutsideOfHook;a=a.depType;var f="function"===a?"useCallback":"useMemo",k="function"===a?"definition":"initialization",h="wrap the "+k+" of '"+b.name.name+"' in its own "+f+"() Hook.";h="The '"+b.name.name+"' "+a+" "+("conditional"===a||"logical expression"===a?"could make":"makes")+" the dependencies of "+(t+" Hook (at line "+e.loc.start.line+") change on every render. ")+(d?"To fix this, "+h:"Move it inside the "+t+" callback. Alternatively, "+ | ||
h);var g;d&&"Variable"===b.type&&"function"===a&&(g=[{desc:"Wrap the "+k+" of '"+b.name.name+"' in its own "+f+"() Hook.",fix:function(a){var c="useMemo"===f?["useMemo(() => { return ","; })"]:["useCallback(",")"],d=c[1];return[a.insertTextBefore(b.node.init,c[0]),a.insertTextAfter(b.node.init,d)]}}]);c({node:b.node,message:h,suggest:g})});else{!h&&0<l.size&&(R=H({dependencies:y,declaredDependencies:[],stableDependencies:M,externalDependencies:L,isEffect:h}).suggestedDependencies);(function(){if(0=== | ||
K.length)return!0;var a=K.map(function(a){return a.key}),b=a.slice().sort();return a.join(",")===b.join(",")})()&&R.sort();n="";if(0<B.size){var S=null;Array.from(B.keys()).forEach(function(a){null===S&&a.endsWith(".current")&&(S=a)});if(null!==S)n=" Mutable values like '"+S+"' aren't valid dependencies because mutating them doesn't re-render the component.";else if(0<L.size){var I=Array.from(L)[0];A.set.has(I)||(n=" Outer scope values like '"+I+"' aren't valid dependencies because mutating them doesn't re-render the component.")}}if(!n&& | ||
l.has("props")){A=y.get("props");if(null==A)return;A=A.references;if(!Array.isArray(A))return;I=!0;for(var Z=0;Z<A.length;Z++){var u=Y(q.block,A[Z].identifier);if(!u){I=!1;break}u=u.parent;if(null==u){I=!1;break}if("MemberExpression"!==u.type&&"OptionalMemberExpression"!==u.type){I=!1;break}}I&&(n=" However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the "+(t+" call and refer to those specific props inside ")+(a.getSource(f)+"."))}if(!n&& | ||
0<l.size){var V=null;l.forEach(function(a){if(!V){var b=q.set.get(a),c=y.get(a);if(c.references[0].resolved===b&&(b=b.defs[0],null!=b&&null!=b.name&&"Parameter"===b.type)){b=!1;for(var d,e=0;e<c.references.length;e++)if(d=c.references[e].identifier,null!=d&&null!=d.parent&&("CallExpression"===d.parent.type||"OptionalCallExpression"===d.parent.type)&&d.parent.callee===d){b=!0;break}b&&(V=a)}}});null!==V&&(n=" If '"+V+"' changes too often, find the parent component that defines it and wrap that definition in useCallback.")}if(!n&& | ||
0<l.size){var v=null;l.forEach(function(a){if(null===v)for(var b=y.get(a).references,c,d,e=0;e<b.length;e++){c=b[e].identifier;for(d=c.parent;null!=d&&d!==q.block;){if("CallExpression"===d.type){var f=w.get(d.callee);if(null!=f){f.name===a?v={missingDep:a,setter:d.callee.name,form:"updater"}:m.has(c)?v={missingDep:a,setter:d.callee.name,form:"reducer"}:(c=b[e].resolved,null!=c&&(c=c.defs[0],null!=c&&"Parameter"===c.type&&(v={missingDep:a,setter:d.callee.name,form:"inlineReducer"})));break}}d=d.parent}if(null!== | ||
v)break}});if(null!==v)switch(v.form){case "reducer":n=" You can also replace multiple useState variables with useReducer if '"+(v.setter+"' needs the current value of '")+(v.missingDep+"'.");break;case "inlineReducer":n=" If '"+v.setter+"' needs the current value of '"+(v.missingDep+"', you can also switch to useReducer instead of useState and read '")+(v.missingDep+"' in the reducer.");break;case "updater":n=" You can also do a functional update '"+v.setter+"("+v.missingDep.substring(0,1)+" => ...)' if you only need '"+ | ||
v.missingDep+"' in the '"+(v.setter+"' call.");break;default:throw Error("Unknown case.");}}c({node:e,message:"React Hook "+a.getSource(f)+" has "+(p(l,"a","missing","include")||p(B,"an","unnecessary","exclude")||p(qa,"a","duplicate","omit"))+n,suggest:[{desc:"Update the dependencies array to be: ["+R.map(C).join(", ")+"]",fix:function(a){return a.replaceText(e,"["+R.map(C).join(", ")+"]")}}]})}}else{var P=null;y.forEach(function(a,b){P||a.references.forEach(function(a){if(!P&&w.has(a.identifier)){for(a= | ||
a.from;"function"!==a.type;)a=a.upper;a.block===d&&(P=b)}})});if(P){var ba=H({dependencies:y,declaredDependencies:[],stableDependencies:M,externalDependencies:new Set,isEffect:!0}).suggestedDependencies;c({node:f,message:"React Hook "+t+" contains a call to '"+P+"'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass ["+ba.join(", ")+("] as a second argument to the "+t+" Hook."),suggest:[{desc:"Add dependencies array: ["+ba.join(", ")+"]",fix:function(a){return a.insertTextAfter(d, | ||
", ["+ba.join(", ")+"]")}}]})}}}}var f=a.options&&a.options[0]&&a.options[0].enableDangerousAutofixThisMayCauseInfiniteLoops||!1,p={additionalHooks:a.options&&a.options[0]&&a.options[0].additionalHooks?new RegExp(a.options[0].additionalHooks):void 0,enableDangerousAutofixThisMayCauseInfiniteLoops:f},g=a.getSourceCode().scopeManager,w=new WeakMap,m=new WeakSet,E=new WeakMap,x=new WeakMap;return{CallExpression:function(b){var e=ua(b.callee,p);if(-1!==e){var f=b.arguments[e],g=b.callee,h=ta(g).name, | ||
m=b.arguments[e+1];b=/Effect($|[^a-z])/g.test(h);if(f)if(m||b){switch(f.type){case "FunctionExpression":case "ArrowFunctionExpression":d(f,m,g,h,b);return;case "Identifier":if(!m||m.elements&&m.elements.some(function(a){return a&&"Identifier"===a.type&&a.name===f.name}))return;e=a.getScope().set.get(f.name);if(null==e||null==e.defs)return;e=e.defs[0];if(!e||!e.node)break;if("Variable"!==e.type&&"FunctionName"!==e.type)break;switch(e.node.type){case "FunctionDeclaration":d(e.node,m,g,h,b);return;case "VariableDeclarator":if(e= | ||
e.node.init)switch(e.type){case "ArrowFunctionExpression":case "FunctionExpression":d(e,m,g,h,b);return}}break;default:c({node:g,message:"React Hook "+h+" received a function whose dependencies are unknown. Pass an inline function instead."});return}c({node:g,message:"React Hook "+h+" has a missing dependency: '"+f.name+"'. Either include it or remove the dependency array.",suggest:[{desc:"Update the dependencies array to be: ["+f.name+"]",fix:function(a){return a.replaceText(m,"["+f.name+"]")}}]})}else"useMemo"!== | ||
h&&"useCallback"!==h||c({node:g,message:"React Hook "+h+" does nothing when called with only one argument. Did you forget to pass an array of dependencies?"});else c({node:g,message:"React Hook "+h+" requires an effect callback. Did you forget to pass a callback to the hook?"})}}}}}}; |
{ | ||
"name": "eslint-plugin-react-hooks", | ||
"description": "ESLint rules for React Hooks", | ||
"version": "4.3.0", | ||
"version": "4.6.0", | ||
"repository": { | ||
@@ -13,3 +13,2 @@ "type": "git", | ||
"README.md", | ||
"build-info.json", | ||
"index.js", | ||
@@ -41,2 +40,2 @@ "cjs" | ||
} | ||
} | ||
} |
Sorry, the diff of this file is too big to display
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
117662
2144
1