wasm_react/hooks/
use_js_ref.rs1use crate::react_bindings;
2use js_sys::Reflect;
3use std::{fmt::Debug, marker::PhantomData};
4use wasm_bindgen::{intern, JsCast, JsValue, UnwrapThrowExt};
5
6pub struct JsRefContainer<T>(JsValue, PhantomData<T>);
8
9impl<T: JsCast> JsRefContainer<T> {
10 pub fn current(&self) -> Option<T> {
12 self.current_untyped().dyn_into::<T>().ok()
13 }
14
15 pub fn current_untyped(&self) -> JsValue {
17 Reflect::get(&self.0, &intern("current").into())
18 .expect_throw("cannot read from ref container")
19 }
20
21 pub fn set_current(&self, value: Option<&T>) {
23 Reflect::set(
24 &self.0,
25 &intern("current").into(),
26 value.map(|t| t.as_ref()).unwrap_or(&JsValue::null()),
27 )
28 .expect_throw("cannot write into ref container");
29 }
30}
31
32impl<T> Debug for JsRefContainer<T> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_tuple("JsRefContainer").field(&self.0).finish()
35 }
36}
37
38impl<T> Clone for JsRefContainer<T> {
39 fn clone(&self) -> Self {
40 Self(self.0.clone(), PhantomData)
41 }
42}
43
44impl<T> AsRef<JsValue> for JsRefContainer<T> {
45 fn as_ref(&self) -> &JsValue {
46 &self.0
47 }
48}
49
50impl<T> From<JsRefContainer<T>> for JsValue {
51 fn from(value: JsRefContainer<T>) -> Self {
52 value.0
53 }
54}
55
56impl<T> From<JsValue> for JsRefContainer<T> {
57 fn from(value: JsValue) -> Self {
58 Self(value, PhantomData)
59 }
60}
61
62pub fn use_js_ref<T: JsCast>(init: Option<T>) -> JsRefContainer<T> {
87 let ref_container = react_bindings::use_ref(
88 &init.map(|init| init.into()).unwrap_or(JsValue::null()),
89 );
90
91 JsRefContainer(ref_container, PhantomData)
92}