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}