1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::fmt::Debug;
use std::rc::Rc;

use super::{use_effect_once, use_effect_update, use_effect_update_with_deps, use_previous};

/// This hook logs in console as component goes through life-cycles.
///
/// # Example
///
/// ```rust
/// # use yew::prelude::*;
/// #
/// use yew_hooks::prelude::*;
///
/// #[function_component(UseLogger)]
/// fn logger(props: &Props) -> Html {
///     use_logger("MyComponent".to_string(), props.clone());
///
///     let c = use_state(|| 0);
///     let d = use_state(|| "d".to_string());
///     use_logger("MyComponent".to_string(), (c.clone(), d.clone()));
///     
///     html! {
///         <>
///             <b>{ " a: " }</b> { props.a }
///             <b>{ " b: " }</b> { &props.b }
///             <b>{ " c: " }</b> { *c }
///             <b>{ " d: " }</b> { &*d }
///         </>
///     }
/// }
///
/// #[derive(Debug, Properties, PartialEq, Clone)]
/// struct Props {
///     pub a: i32,
///     pub b: String,
/// }
/// ```
pub fn use_logger<T>(name: String, props: T)
where
    T: Debug + 'static,
{
    let name = Rc::new(name);
    let props = Rc::new(props);

    {
        let name = name.clone();
        let props = props.clone();

        use_effect_once(move || {
            log::debug!("{} mounted: {:?}", name, props);

            move || log::debug!("{} unmounted", name)
        });
    }

    use_effect_update(move || {
        log::debug!("{} updated: {:?}", name, props);
        || ()
    });
}

/// This hook logs in console as component goes through life-cycles.
/// Like [`use_logger`] but only logs when `prev_state != next_state`.
/// This requires the props to implement [`PartialEq`].
///
/// # Example
///
/// ```rust
/// # use yew::prelude::*;
/// #
/// use yew_hooks::prelude::*;
///
/// #[function_component(UseLogger)]
/// fn logger(props: &Props) -> Html {
///     use_logger_eq("MyComponent".to_string(), props.clone());
///
///     let c = use_state(|| 0);
///     let d = use_state(|| "d".to_string());
///     use_logger_eq("MyComponent".to_string(), (c.clone(), d.clone()));
///     
///     html! {
///         <>
///             <b>{ " a: " }</b> { props.a }
///             <b>{ " b: " }</b> { &props.b }
///             <b>{ " c: " }</b> { *c }
///             <b>{ " d: " }</b> { &*d }
///         </>
///     }
/// }
///
/// #[derive(Debug, Properties, PartialEq, Clone)]
/// struct Props {
///     pub a: i32,
///     pub b: String,
/// }
/// ```
pub fn use_logger_eq<T>(name: String, props: T)
where
    T: Debug + PartialEq + 'static,
{
    let name = Rc::new(name);
    let props = Rc::new(props);
    let props_prev = use_previous(props.clone());

    {
        let name = name.clone();
        let props = props.clone();

        use_effect_once(move || {
            log::debug!("{} mounted: {:?}", name, props);

            move || log::debug!("{} unmounted", name)
        });
    }

    use_effect_update_with_deps(
        move |props| {
            log::debug!("{} updated: from {:?}, to {:?}", name, *props_prev, props);
            || ()
        },
        props,
    );
}