react/use_ref/
use_ref_readonly.rs1use std::rc::Rc;
2
3use wasm_bindgen::UnwrapThrowExt;
4
5use super::ReadRef;
6
7#[derive(Debug)]
8pub struct ReadRefRc<T: ?Sized>(pub Rc<T>);
9
10impl<T: ?Sized> Clone for ReadRefRc<T> {
11 #[inline]
12 fn clone(&self) -> Self {
13 Self(Rc::clone(&self.0))
14 }
15}
16
17impl<T: ?Sized> PartialEq for ReadRefRc<T> {
18 #[inline]
19 fn eq(&self, other: &Self) -> bool {
20 Rc::ptr_eq(&self.0, &other.0)
21 }
22}
23
24impl<T: ?Sized> Eq for ReadRefRc<T> {}
25
26impl<T: ?Sized> ReadRef<Rc<T>> for ReadRefRc<T> {
27 #[inline]
28 fn current(&self) -> Rc<T> {
29 Rc::clone(&self.0)
30 }
31}
32
33pub fn use_ref_readonly<T: 'static + ?Sized>(initial_rc: Rc<T>) -> ReadRefRc<T> {
34 use_ref_readonly_with(move || initial_rc)
35}
36
37pub fn use_ref_readonly_with<T: 'static + ?Sized, F: FnOnce() -> Rc<T>>(
38 get_initial_rc: F,
39) -> ReadRefRc<T> {
40 let obj = react_sys::use_ref_optional_usize(None);
41
42 let k = obj.current();
43
44 let (k, v) = if let Some(k) = k {
45 let v = unsafe { forgotten::try_get_with_usize::<Rc<T>>(&k) };
46 let v =
47 v.expect_throw("use_ref_readonly ptr is expected to be valid before element unmounted");
48 let v = Rc::clone(v.as_ref());
49 (k, v)
50 } else {
51 let rc: Rc<T> = get_initial_rc();
52 let k = forgotten::forget(Rc::clone(&rc));
53 let k = *k.into_shared().as_usize();
54 obj.set_current(Some(k));
55 (k, rc)
56 };
57
58 crate::use_effect_on_mounted(move || {
60 move || {
61 unsafe { forgotten::try_free_with_usize(k) };
63 }
64 });
65
66 ReadRefRc(v)
67}