yew_side_effect/comps/
side_effect.rs

1use std::rc::Rc;
2
3use yew::prelude::*;
4
5use crate::hooks::use_store;
6use crate::store::Message;
7use crate::utils::Id;
8
9#[derive(Properties, PartialEq)]
10pub struct SideEffectProps<T: PartialEq + 'static> {
11    pub value: Rc<T>,
12}
13
14impl<T> Clone for SideEffectProps<T>
15where
16    T: PartialEq + 'static,
17{
18    fn clone(&self) -> Self {
19        Self {
20            value: self.value.clone(),
21        }
22    }
23}
24
25/// Registers a single side effect.
26///
27/// Each `SideEffect<T>` accepts a `Rc<T>` as value, it will be stored in order of creation.
28///
29/// ```
30/// use yew::prelude::*;
31/// use std::rc::Rc;
32/// use yew_side_effect::SideEffect;
33///
34/// #[derive(Debug, Clone, PartialEq)]
35/// pub struct SideEffectA {
36///     value: String,
37/// }
38///
39/// let val = Rc::new(SideEffectA {
40///     value: "My Side Effect!".into(),
41/// });
42///
43/// let rendered = html! {<SideEffect<SideEffectA> value={val} />};
44/// ```
45#[function_component(SideEffect)]
46pub fn side_effect<T>(props: &SideEffectProps<T>) -> Html
47where
48    T: PartialEq + 'static,
49{
50    let id = use_state(Id::new);
51    let store = use_store().expect("No context set.");
52    let store_id = store.id();
53
54    let store_clone = store.clone();
55    use_effect_with_deps(
56        move |(_, value, id)| {
57            if (*store_clone).has(id) {
58                store_clone.dispatch(Message::Update((id.clone(), value.clone())));
59            } else {
60                store_clone.dispatch(Message::Add((id.clone(), value.clone())));
61            }
62            || {}
63        },
64        (store_id.clone(), props.value.clone(), (*id).clone()),
65    );
66
67    use_effect_with_deps(
68        move |(_, id)| {
69            let id = id.clone();
70
71            move || store.dispatch(Message::Remove(id.clone()))
72        },
73        (store_id, (*id).clone()),
74    );
75
76    Html::default()
77}