Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: useListener hook #389

Open
gruvw opened this issue Oct 22, 2023 · 3 comments · May be fixed by #390
Open

Feature Request: useListener hook #389

gruvw opened this issue Oct 22, 2023 · 3 comments · May be fixed by #390
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@gruvw
Copy link

gruvw commented Oct 22, 2023

Is your feature request related to a problem? Please describe.

When using Listenable with useEffect it can be a bit cumbersome to always repeat the same boilerplate off addListener and removeListener again and again:

  • Having to call keys.length times addListener
  • Duplication of key in keys and key.addListener(...) for each key
  • Extra level of indentation when writing the listener inside the useEffect closure

Describe the solution you'd like

Add a useListener hook.

void useListener(void Function() listener, List<Listenable> listenables) {
  useEffect(() {
    final listenable = Listenable.merge(listenables);
    listenable.addListener(listener);

    return () => listenable.removeListener(listener);
  }, listenables);
}

Additional context

This would be very useful to bind values when some controller changes:

final nameError = useState<String?>(null);
final nameController = useTextEditingController();

useListener(() {
  final validation = nameValidation(offlineNameController.text);
  nameError.value = validation.nameError;
}, [nameController]);

and even when it depends on multiple controllers like:

final activeTab = useState(_initialTab);
final primaryTabController = useTabController(
  initialLength: Tabs.primaryTabLength,
  initialIndex: activeTab.value.primaryTabIndex,
);
final secondaryTabController = useTabController(
  initialLength: Tabs.secondaryTabLength,
  initialIndex: activeTab.value.secondaryTabIndex,
);

useListener(() {
  activeTab.value = Tabs.of(
    primaryTabController.index,
    secondaryTabController.index,
  );
}, [
  primaryTabController,
  secondaryTabController,
]);
@rrousselGit
Copy link
Owner

The naming would more more "useOnListenableChange", like "useOnStreamChange"
And it would take a single listenable, not a list of listenable.

Otherwise LGTM. Feel free to make a PR if you want to :)

@rrousselGit rrousselGit added the good first issue Good for newcomers label Oct 23, 2023
@gruvw
Copy link
Author

gruvw commented Oct 23, 2023

Ok sure I will try and make a PR! Let me know if I mess up something doing so as it's only my second one :)

However why not a list of listenables ? It's more convenient isn't it ?

@rrousselGit
Copy link
Owner

Folks wanting to listen to multiple listenables can use the hook multiple times or use Listenable.merge

It's rare that they'll want to listen to multiple listenables at once.

gruvw added a commit to gruvw/flutter_hooks that referenced this issue Oct 23, 2023
@gruvw gruvw linked a pull request Oct 23, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants