-
-
Notifications
You must be signed in to change notification settings - Fork 188
Open
Labels
Description
[Feature Request] Add useAcross()
hook for cross-method data sharing
Problem Statement
When decomposing UI into multiple methods within a HookWidget
, there's often a need to share values across different methods. Current solutions have their own limitations:
Current Solutions and Their Problems:
1. Method Parameter Passing
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
final controller = useTextEditingController();
final focusNode = useFocusNode();
return Column(
children: [
_buildInput(controller, focusNode), // Too many parameters
_buildButtons(controller, focusNode), // Repetitive passing
],
);
}
Widget _buildInput(TextEditingController controller, FocusNode focusNode) { ... }
Widget _buildButtons(TextEditingController controller, FocusNode focusNode) { ... }
}
Problems: Long parameter lists, repetitive passing, difficult to maintain
2. Inlining methods into build
Widget build(BuildContext context) {
final controller = useTextEditingController();
final focusNode = useFocusNode();
return Column(
children: [
// All UI logic crammed into build method, hard to read
TextField(controller: controller, focusNode: focusNode),
Row(
children: [
ElevatedButton(onPressed: () => controller.clear(), ...),
ElevatedButton(onPressed: () => focusNode.requestFocus(), ...),
],
),
],
);
}
Problems: Bloated build method, poor readability, defeats the purpose of method decomposition
Proposed Solution: useAcross()
Hook
useAcross
allows sharing hook values across different methods within the same HookWidget
without parameter passing:
typedef _Holder = ({
TextEditingController controller,
FocusNode focusNode,
ValueNotifier<bool> isValid,
});
class MyWidget extends HookWidget {
@override
Widget build(BuildContext context) {
final controller = useTextEditingController();
final focusNode = useFocusNode();
// Store all hooks that need to be shared
useAcross<_Holder>((
controller: controller,
focusNode: focusNode,
));
return Column(
children: [
_buildInput(), // No parameter passing needed
_buildButton(), // Clean and simple
],
);
}
Widget _buildInput() {
final _Holder(:controller, :focusNode) = useAcross<_Holder>();
return TextField(controller: controller, focusNode: focusNode);
}
Widget _buildButton() {
final _Holder(:controller) = useAcross<_Holder>();
return Row(
children: [
ElevatedButton(onPressed: () => controller.clear(), ...),
],
);
}
}
Implementation
T useAcross<T>([T? value]) {
final context = useContext();
if (value != null) {
_container[context] = value;
return value;
} else {
return _container[context] as T;
}
}
final Expando _container = Expando();