yew_side_effect/comps/
provider.rs

1use std::rc::Rc;
2
3use yew::prelude::*;
4
5use crate::SideEffects;
6
7use crate::hooks::StoreCtx;
8use crate::store::Store;
9
10#[derive(Properties)]
11pub struct ProviderProps<T: PartialEq + 'static> {
12    pub children: Children,
13    pub on_change: Rc<dyn Fn(SideEffects<T>)>,
14}
15
16#[allow(clippy::vtable_address_comparisons)]
17impl<T> PartialEq for ProviderProps<T>
18where
19    T: PartialEq + 'static,
20{
21    fn eq(&self, rhs: &Self) -> bool {
22        self.children == rhs.children && Rc::ptr_eq(&self.on_change, &rhs.on_change)
23    }
24}
25
26impl<T> Clone for ProviderProps<T>
27where
28    T: PartialEq + 'static,
29{
30    fn clone(&self) -> Self {
31        Self {
32            children: self.children.clone(),
33            on_change: self.on_change.clone(),
34        }
35    }
36}
37
38/// Provider of a Side Effect.
39///
40/// You should register this title provider like a react context provider.
41///
42/// It accepts a function `on_change` which is called when side effect changes.
43#[function_component(SideEffectProvider)]
44pub fn side_effect_provider<T>(props: &ProviderProps<T>) -> Html
45where
46    T: PartialEq + 'static,
47{
48    let children = props.children.clone();
49
50    let store = use_reducer(Store::new);
51
52    use_effect_with_deps(
53        |(side_effects, props)| {
54            let on_change = props.on_change.clone();
55            on_change(side_effects.clone());
56            || {}
57        },
58        ((*store).get(), props.clone()),
59    );
60
61    html! { <ContextProvider<StoreCtx<T>> context={store}>{children}</ContextProvider<StoreCtx<T>>> }
62}