File tree Expand file tree Collapse file tree 2 files changed +56
-2
lines changed
packages/eslint-plugin-react-hooks Expand file tree Collapse file tree 2 files changed +56
-2
lines changed Original file line number Diff line number Diff line change @@ -1324,6 +1324,34 @@ const allTests = {
13241324 ` ,
13251325 errors : [ asyncComponentHookError ( 'use' ) ] ,
13261326 } ,
1327+ {
1328+ code : normalizeIndent `
1329+ function App({p1, p2}) {
1330+ try {
1331+ use(p1);
1332+ } catch (error) {
1333+ console.error(error);
1334+ }
1335+ use(p2);
1336+ return <div>App</div>;
1337+ }
1338+ ` ,
1339+ errors : [ tryCatchUseError ( 'use' ) ] ,
1340+ } ,
1341+ {
1342+ code : normalizeIndent `
1343+ function App({p1, p2}) {
1344+ try {
1345+ doSomething();
1346+ } catch {
1347+ use(p1);
1348+ }
1349+ use(p2);
1350+ return <div>App</div>;
1351+ }
1352+ ` ,
1353+ errors : [ tryCatchUseError ( 'use' ) ] ,
1354+ } ,
13271355 ] ,
13281356} ;
13291357
@@ -1383,7 +1411,7 @@ if (__EXPERIMENTAL__) {
13831411 const onEvent = useEffectEvent((text) => {
13841412 console.log(text);
13851413 });
1386-
1414+
13871415 useEffect(() => {
13881416 onEvent('Hello world');
13891417 });
@@ -1421,7 +1449,7 @@ if (__EXPERIMENTAL__) {
14211449 });
14221450 return <Child onClick={() => onClick()} />
14231451 }
1424-
1452+
14251453 // The useEffectEvent function shares an identifier name with the above
14261454 function MyLastComponent({theme}) {
14271455 const onClick = useEffectEvent(() => {
@@ -1573,6 +1601,12 @@ function asyncComponentHookError(fn) {
15731601 } ;
15741602}
15751603
1604+ function tryCatchUseError ( fn ) {
1605+ return {
1606+ message : `React Hook "${ fn } " cannot be called in a try/catch block.` ,
1607+ } ;
1608+ }
1609+
15761610// For easier local testing
15771611if ( ! process . env . CI ) {
15781612 let only = [ ] ;
Original file line number Diff line number Diff line change @@ -111,6 +111,16 @@ function isInsideDoWhileLoop(node: Node | undefined): node is DoWhileStatement {
111111 return false ;
112112}
113113
114+ function isInsideTryCatch ( node : Node | undefined ) : boolean {
115+ while ( node ) {
116+ if ( node . type === 'TryStatement' || node . type === 'CatchClause' ) {
117+ return true ;
118+ }
119+ node = node . parent ;
120+ }
121+ return false ;
122+ }
123+
114124function isUseEffectEventIdentifier ( node : Node ) : boolean {
115125 if ( __EXPERIMENTAL__ ) {
116126 return node . type === 'Identifier' && node . name === 'useEffectEvent' ;
@@ -532,6 +542,16 @@ const rule = {
532542 continue ;
533543 }
534544
545+ // Report an error if use() is called inside try/catch/finally.
546+ if ( isUseIdentifier ( hook ) && isInsideTryCatch ( hook ) ) {
547+ context . report ( {
548+ node : hook ,
549+ message : `React Hook "${ getSourceCode ( ) . getText (
550+ hook ,
551+ ) } " cannot be called in a try/catch/finally block.`,
552+ } ) ;
553+ }
554+
535555 // Report an error if a hook may be called more then once.
536556 // `use(...)` can be called in loops.
537557 if (
You can’t perform that action at this time.
0 commit comments