prefer_use_prefix
v0.4.0 Warning Fix Hook Rules
This rule flags a function or method that calls a hook but is not itself named like one. A function that calls useState, useMemoized, or any other useX() is a custom hook, and must be named useSomething — or _useSomething when private.
Why use this rule
Section titled “Why use this rule”The name is not decoration: it is how the rest of the tooling knows the call has to obey the rules of hooks. avoid_conditional_hooks, avoid_hooks_outside_build and flutter_hooks itself all recognise a hook by its use prefix. Call _fetchData() from inside an if, and nothing warns you — even though it allocates a hook slot and will corrupt the slot order.
The quick fix renames the declaration for you.
See also: flutter_hooks — custom hooks
import 'package:flutter/material.dart';import 'package:flutter_hooks/flutter_hooks.dart';
// A helper that calls a hook is a hook, whatever it is called.ValueNotifier<int> counterState() { // LINT return useState(0);}
class CartPage extends HookWidget { const CartPage({super.key});
// A private method is no different — it still allocates a hook slot. ValueNotifier<int> _quantity() { // LINT return useState(1); }
@override Widget build(BuildContext context) { final quantity = _quantity(); return Text('${quantity.value}'); }}import 'package:flutter/material.dart';import 'package:flutter_hooks/flutter_hooks.dart';
ValueNotifier<int> useCounterState() { return useState(0);}
class CartPage extends HookWidget { const CartPage({super.key});
ValueNotifier<int> _useQuantity() { return useState(1); }
@override Widget build(BuildContext context) { final quantity = _useQuantity(); return Text('${quantity.value}'); }}Composing several hooks
Section titled “Composing several hooks”The prefix matters most on a helper that bundles hooks, because that is what other code will call from inside a branch if nothing stops it:
// Don't({ValueNotifier<String> query, TextEditingController controller}) searchState() { final query = useState(''); final controller = useTextEditingController(); return (query: query, controller: controller);}
// Do({ValueNotifier<String> query, TextEditingController controller})useSearchState() { final query = useState(''); final controller = useTextEditingController(); return (query: query, controller: controller);}Known limitations
Section titled “Known limitations”Nothing without a hook call is reported. An ordinary helper keeps its ordinary name — int subtotal() => 42; is not a hook and is left alone.
@override methods are skipped. build calls hooks by design, and so may an overridden method your base class declares; renaming either is not an option, so the rule never asks.
Hooks are recognised by name. The check looks for a call matching use followed by an uppercase letter or a digit. A hook aliased to another name is not seen, and a plain function called useTitleCase counts as one.
Anonymous callbacks have no name to fix. A HookBuilder(builder: (context) { ... }) closure is a legitimate hook context and is not reported.
Configuration
Section titled “Configuration”This rule is in the pedantic preset, so it is enabled by preset: pedantic or by name:
rules: prefer_use_prefix: trueTo turn it off again:
rules: prefer_use_prefix: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”prefer_use_callback— Use ‘useCallback’ instead of ‘useMemoized’ for memoizing functions.avoid_hooks_outside_build— Only call hooks from a hook context.avoid_misused_hooks— Don’t call hooks inside loops.avoid_unnecessary_enum_prefix— Drop an enum name repeated in its own constants.