use_callback.rs 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. use dioxus_core::prelude::use_hook;
  2. use dioxus_signals::CopyValue;
  3. use dioxus_signals::Writable;
  4. /// A callback that's always current
  5. ///
  6. /// Whenever this hook is called the inner callback will be replaced with the new callback but the handle will remain.
  7. ///
  8. /// There is *currently* no signal tracking on the Callback so anything reading from it will not be updated.
  9. ///
  10. /// This API is in flux and might not remain.
  11. pub fn use_callback<O>(f: impl FnMut() -> O + 'static) -> UseCallback<O> {
  12. // Create a copyvalue with no contents
  13. // This copyvalue is generic over F so that it can be sized properly
  14. let mut inner = use_hook(|| CopyValue::new(None));
  15. // Every time this hook is called replace the inner callback with the new callback
  16. inner.set(Some(f));
  17. // And then wrap that callback in a boxed callback so we're blind to the size of the actual callback
  18. use_hook(|| UseCallback {
  19. inner: CopyValue::new(Box::new(move || {
  20. inner.with_mut(|f: &mut Option<_>| f.as_mut().unwrap()())
  21. })),
  22. })
  23. }
  24. /// This callback is not generic over a return type so you can hold a bunch of callbacks at once
  25. ///
  26. /// If you need a callback that returns a value, you can simply wrap the closure you pass in that sets a value in its scope
  27. #[derive(PartialEq)]
  28. pub struct UseCallback<O: 'static + ?Sized> {
  29. inner: CopyValue<Box<dyn FnMut() -> O>>,
  30. }
  31. impl<O: 'static + ?Sized> Clone for UseCallback<O> {
  32. fn clone(&self) -> Self {
  33. Self { inner: self.inner }
  34. }
  35. }
  36. impl<O: 'static> Copy for UseCallback<O> {}
  37. impl<O> UseCallback<O> {
  38. /// Call the callback
  39. pub fn call(&mut self) -> O {
  40. self.inner.with_mut(|f| f())
  41. }
  42. }