useref.rs 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. use std::{
  2. cell::{Cell, Ref, RefCell, RefMut},
  3. rc::Rc,
  4. };
  5. use dioxus_core::Context;
  6. pub fn use_ref<T: 'static>(cx: Context, f: impl FnOnce() -> T) -> UseRef<T> {
  7. cx.use_hook(
  8. |_| UseRefInner {
  9. update_scheduled: Cell::new(false),
  10. update_callback: cx.schedule_update(),
  11. value: RefCell::new(f()),
  12. },
  13. |inner| {
  14. inner.update_scheduled.set(false);
  15. UseRef { inner }
  16. },
  17. )
  18. }
  19. pub struct UseRef<'a, T> {
  20. inner: &'a UseRefInner<T>,
  21. }
  22. struct UseRefInner<T> {
  23. update_scheduled: Cell<bool>,
  24. update_callback: Rc<dyn Fn()>,
  25. value: RefCell<T>,
  26. }
  27. impl<'a, T> UseRef<'a, T> {
  28. pub fn read(&self) -> Ref<'_, T> {
  29. self.inner.value.borrow()
  30. }
  31. pub fn set(&self, new: T) {
  32. *self.inner.value.borrow_mut() = new;
  33. self.needs_update();
  34. }
  35. pub fn read_write(&self) -> (Ref<'_, T>, &Self) {
  36. (self.read(), self)
  37. }
  38. /// Calling "write" will force the component to re-render
  39. pub fn write(&self) -> RefMut<'_, T> {
  40. self.needs_update();
  41. self.inner.value.borrow_mut()
  42. }
  43. /// Allows the ability to write the value without forcing a re-render
  44. pub fn write_silent(&self) -> RefMut<'_, T> {
  45. self.inner.value.borrow_mut()
  46. }
  47. pub fn needs_update(&self) {
  48. if !self.inner.update_scheduled.get() {
  49. self.inner.update_scheduled.set(true);
  50. (self.inner.update_callback)();
  51. }
  52. }
  53. }
  54. impl<T> Clone for UseRef<'_, T> {
  55. fn clone(&self) -> Self {
  56. Self { inner: self.inner }
  57. }
  58. }
  59. impl<T> Copy for UseRef<'_, T> {}