File tree Expand file tree Collapse file tree 2 files changed +65
-3
lines changed
packages/eslint-plugin-react-hooks Expand file tree Collapse file tree 2 files changed +65
-3
lines changed Original file line number Diff line number Diff line change @@ -1324,6 +1324,34 @@ const allTests = {
1324
1324
` ,
1325
1325
errors : [ asyncComponentHookError ( 'use' ) ] ,
1326
1326
} ,
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
+ } ,
1327
1355
] ,
1328
1356
} ;
1329
1357
@@ -1383,7 +1411,7 @@ if (__EXPERIMENTAL__) {
1383
1411
const onEvent = useEffectEvent((text) => {
1384
1412
console.log(text);
1385
1413
});
1386
-
1414
+
1387
1415
useEffect(() => {
1388
1416
onEvent('Hello world');
1389
1417
});
@@ -1421,7 +1449,7 @@ if (__EXPERIMENTAL__) {
1421
1449
});
1422
1450
return <Child onClick={() => onClick()} />
1423
1451
}
1424
-
1452
+
1425
1453
// The useEffectEvent function shares an identifier name with the above
1426
1454
function MyLastComponent({theme}) {
1427
1455
const onClick = useEffectEvent(() => {
@@ -1573,6 +1601,12 @@ function asyncComponentHookError(fn) {
1573
1601
} ;
1574
1602
}
1575
1603
1604
+ function tryCatchUseError ( fn ) {
1605
+ return {
1606
+ message : `React Hook "${ fn } " cannot be called in a try/catch block.` ,
1607
+ } ;
1608
+ }
1609
+
1576
1610
// For easier local testing
1577
1611
if ( ! process . env . CI ) {
1578
1612
let only = [ ] ;
Original file line number Diff line number Diff line change 7
7
/* eslint-disable no-for-of-loops/no-for-of-loops */
8
8
9
9
import type { Rule , Scope } from 'eslint' ;
10
- import type { CallExpression , DoWhileStatement , Node } from 'estree' ;
10
+ import type {
11
+ CallExpression ,
12
+ CatchClause ,
13
+ DoWhileStatement ,
14
+ Node ,
15
+ TryStatement ,
16
+ } from 'estree' ;
11
17
12
18
// @ts -expect-error untyped module
13
19
import CodePathAnalyzer from '../code-path-analysis/code-path-analyzer' ;
@@ -111,6 +117,18 @@ function isInsideDoWhileLoop(node: Node | undefined): node is DoWhileStatement {
111
117
return false ;
112
118
}
113
119
120
+ function isInsideTryCatch (
121
+ node : Node | undefined ,
122
+ ) : node is TryStatement | CatchClause {
123
+ while ( node ) {
124
+ if ( node . type === 'TryStatement' || node . type === 'CatchClause' ) {
125
+ return true ;
126
+ }
127
+ node = node . parent ;
128
+ }
129
+ return false ;
130
+ }
131
+
114
132
function isUseEffectEventIdentifier ( node : Node ) : boolean {
115
133
if ( __EXPERIMENTAL__ ) {
116
134
return node . type === 'Identifier' && node . name === 'useEffectEvent' ;
@@ -532,6 +550,16 @@ const rule = {
532
550
continue ;
533
551
}
534
552
553
+ // Report an error if use() is called inside try/catch.
554
+ if ( isUseIdentifier ( hook ) && isInsideTryCatch ( hook ) ) {
555
+ context . report ( {
556
+ node : hook ,
557
+ message : `React Hook "${ getSourceCode ( ) . getText (
558
+ hook ,
559
+ ) } " cannot be called in a try/catch block.`,
560
+ } ) ;
561
+ }
562
+
535
563
// Report an error if a hook may be called more then once.
536
564
// `use(...)` can be called in loops.
537
565
if (
You can’t perform that action at this time.
0 commit comments