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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::{react_bindings, Persisted, PersistedOrigin};
use js_sys::Reflect;
use std::{fmt::Debug, marker::PhantomData};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
pub struct JsRefContainer<T>(JsValue, PhantomData<T>);
impl<T: JsCast> JsRefContainer<T> {
pub fn current(&self) -> Option<T> {
self.current_untyped().dyn_into::<T>().ok()
}
pub fn current_untyped(&self) -> JsValue {
Reflect::get(&self.0, &"current".into())
.expect_throw("cannot read from ref container")
}
pub fn set_current(&self, value: Option<&T>) {
Reflect::set(
&self.0,
&"current".into(),
value.map(|t| t.as_ref()).unwrap_or(&JsValue::null()),
)
.expect_throw("cannot write into ref container");
}
}
impl<T: 'static> Persisted for JsRefContainer<T> {
fn ptr(&self) -> PersistedOrigin {
PersistedOrigin
}
}
impl<T> Debug for JsRefContainer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("JsRefContainer").field(&self.0).finish()
}
}
impl<T> Clone for JsRefContainer<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), PhantomData)
}
}
impl<T> AsRef<JsValue> for JsRefContainer<T> {
fn as_ref(&self) -> &JsValue {
&self.0
}
}
impl<T> From<JsRefContainer<T>> for JsValue {
fn from(value: JsRefContainer<T>) -> Self {
value.0
}
}
pub fn use_js_ref<T: JsCast>(init: Option<T>) -> JsRefContainer<T> {
let ref_container = react_bindings::use_ref(
&init.map(|init| init.into()).unwrap_or(JsValue::null()),
);
JsRefContainer(ref_container, PhantomData)
}