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