@@ -100,6 +100,16 @@ function isInsideComponentOrHook(node) {
100100 return false ;
101101}
102102
103+ function isInsideDoWhileLoop ( node ) {
104+ while ( node ) {
105+ if ( node . type === 'DoWhileStatement' ) {
106+ return true ;
107+ }
108+ node = node . parent ;
109+ }
110+ return false ;
111+ }
112+
103113function isUseEffectEventIdentifier ( node ) {
104114 if ( __EXPERIMENTAL__ ) {
105115 return node . type === 'Identifier' && node . name === 'useEffectEvent' ;
@@ -295,7 +305,7 @@ export default {
295305 if ( pathList . has ( segment . id ) ) {
296306 const pathArray = Array . from ( pathList ) ;
297307 const cyclicSegments = pathArray . slice (
298- pathArray . indexOf ( segment . id ) - 1 ,
308+ pathArray . indexOf ( segment . id ) + 1 ,
299309 ) ;
300310 for ( const cyclicSegment of cyclicSegments ) {
301311 cyclic . add ( cyclicSegment ) ;
@@ -485,7 +495,10 @@ export default {
485495 for ( const hook of reactHooks ) {
486496 // Report an error if a hook may be called more then once.
487497 // `use(...)` can be called in loops.
488- if ( cycled && ! isUseIdentifier ( hook ) ) {
498+ if (
499+ ( cycled || isInsideDoWhileLoop ( hook ) ) &&
500+ ! isUseIdentifier ( hook )
501+ ) {
489502 context . report ( {
490503 node : hook ,
491504 message :
@@ -520,7 +533,8 @@ export default {
520533 if (
521534 ! cycled &&
522535 pathsFromStartToEnd !== allPathsFromStartToEnd &&
523- ! isUseIdentifier ( hook ) // `use(...)` can be called conditionally.
536+ ! isUseIdentifier ( hook ) && // `use(...)` can be called conditionally.
537+ ! isInsideDoWhileLoop ( hook ) // wrapping do/while loops are checked separately.
524538 ) {
525539 const message =
526540 `React Hook "${ getSource ( hook ) } " is called ` +
0 commit comments