bloom_core/
object_ref.rs

1use std::sync::Arc;
2
3use async_context::with_async_context_mut;
4
5use crate::hook::Hook;
6
7/// use_ref can be used to obtain a persistent reference to an object.
8/// The object returned from ref is guaranteed to be the same object
9/// on every subsequent call to a component's render-function.
10/// The most common use case is with HtmlNodes:
11/// ```
12/// let my_div = use_ref::<DomRef>()
13///
14/// rsx!(
15///     <div ref=my_div />
16/// )
17/// ```
18/// where my_div will contain a reference to the div element after it has been rendered.
19///
20/// This can be used in an effect to manipulate the DOM directly:
21/// ```
22/// use_effect((), |_| {
23///     my_div.get().set_inner_text("Hello, world!");
24/// })
25/// ```
26pub fn use_ref<T>() -> Arc<T>
27where
28    T: Default + Send + Sync + 'static,
29{
30    with_async_context_mut(|hook: Option<&mut Hook>| {
31        if let Some(hook) = hook {
32            let object_ref = hook
33                .refs
34                .entry(hook.ref_index)
35                .or_insert_with(|| Arc::new(T::default()));
36            hook.ref_index += 1;
37            object_ref
38                .clone()
39                .downcast()
40                .expect("Hook Invariant Violation: Failed to cast ref")
41        } else {
42            Arc::new(T::default())
43        }
44    })
45}
46
47pub fn use_ref_with_default<T, D>(default: D) -> Arc<T>
48where
49    T: Send + Sync + 'static,
50    D: FnOnce() -> T,
51{
52    with_async_context_mut(|hook: Option<&mut Hook>| {
53        if let Some(hook) = hook {
54            let object_ref = hook
55                .refs
56                .entry(hook.ref_index)
57                .or_insert_with(|| Arc::new(default()));
58            hook.ref_index += 1;
59            object_ref
60                .clone()
61                .downcast()
62                .expect("Hook Invariant Violation: Failed to cast ref")
63        } else {
64            Arc::new(default())
65        }
66    })
67}