avoid_conditional_hooks
v0.4.0 Warning Widget Best Practices
This rule flags hook calls (useState, useMemoized, useEffect, etc.) that appear inside if statements, ternary expressions, switch cases, or short-circuit operators (&&, ||). Hooks must be called in the exact same order on every build, and conditional execution breaks that guarantee.
Why use this rule
Section titled “Why use this rule”The hooks framework tracks state by call order, not by name. If a hook is skipped on one build because a condition is false, every subsequent hook shifts position and reads the wrong state. This leads to bizarre bugs where values swap between hooks or the app crashes with an index-out-of-range error. This is the same “Rules of Hooks” constraint from React.
See also: flutter_hooks | React Rules of Hooks
class MyWidget extends HookWidget { final bool condition;
@override Widget build(BuildContext context) { // Hook called conditionally — order changes between builds if (condition) { final value = useMemoized(() => 42); } return const Text('Hello'); }}class MyWidget extends HookWidget { final bool condition;
@override Widget build(BuildContext context) { // Hook always called, conditional logic inside final value = useMemoized(() { if (condition) return 42; return 0; }); return Text('$value'); }}Configuration
Section titled “Configuration”To disable this rule:
plugins: many_lints: diagnostics: avoid_conditional_hooks: false