respo/node/component/
effect.rs

1mod base;
2
3use std::{any::Any, fmt::Debug, rc::Rc};
4
5use base::RespoEffectDynEq;
6use cirru_parser::Cirru;
7use web_sys::Node;
8
9/// trait for component effects
10/// you can declare `mounted`, `beforeUpdate`, `updated`, `beforeUnmount` methods
11/// to handle lifecycle events, mainly for manually manipulating DOM
12pub trait RespoEffect
13where
14  Self: Debug + Any + RespoEffectDynEq + 'static,
15{
16  /// actually run effect
17  #[allow(unused_variables)]
18  fn run(&self, effect_type: RespoEffectType, el: &Node) -> Result<(), String> {
19    match effect_type {
20      RespoEffectType::Mounted => self.mounted(el),
21      RespoEffectType::BeforeUpdate => self.before_update(el),
22      RespoEffectType::Updated => self.updated(el),
23      RespoEffectType::BeforeUnmount => self.before_unmount(el),
24    }
25  }
26  /// called when mounted
27  #[allow(unused_variables)]
28  fn mounted(&self, el: &Node) -> Result<(), String> {
29    Ok(())
30  }
31  /// called when before update
32  #[allow(unused_variables)]
33  fn before_update(&self, el: &Node) -> Result<(), String> {
34    Ok(())
35  }
36  /// called when updated
37  #[allow(unused_variables)]
38  fn updated(&self, el: &Node) -> Result<(), String> {
39    Ok(())
40  }
41  /// called when before unmount
42  #[allow(unused_variables)]
43  fn before_unmount(&self, el: &Node) -> Result<(), String> {
44    Ok(())
45  }
46}
47
48/// wraps dyn trait object of effect
49#[derive(Debug, Clone)]
50pub struct RespoEffectBox(pub Rc<dyn RespoEffect>);
51
52impl PartialEq for RespoEffectBox {
53  fn eq(&self, other: &Self) -> bool {
54    let r = self.0.as_ref();
55    r.do_eq(other.0.as_ref() as &dyn RespoEffectDynEq) == Some(true)
56  }
57}
58impl Eq for RespoEffectBox {}
59
60impl RespoEffectBox {
61  pub fn new<T>(v: T) -> Self
62  where
63    T: RespoEffect + 'static,
64  {
65    Self(Rc::new(v))
66  }
67}
68
69// use crate::{log, util::print_type_of};
70
71/// Internal enum for effect types.
72/// you only need this if you override `RespoEffect` `.run()`.
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum RespoEffectType {
75  /// called after mounting happened, use effect handlers from new trees
76  Mounted,
77  /// called before effect arguments changed, use effect hanles from new trees
78  BeforeUpdate,
79  /// called after effect arguments changed, use effect handles from new trees
80  Updated,
81  /// called before unmounting, use effect handles from **old** trees
82  BeforeUnmount,
83}
84
85impl From<RespoEffectType> for Cirru {
86  fn from(effect_type: RespoEffectType) -> Self {
87    match effect_type {
88      RespoEffectType::Mounted => "::mounted".into(),
89      RespoEffectType::BeforeUpdate => "::before-update".into(),
90      RespoEffectType::Updated => "::updated".into(),
91      RespoEffectType::BeforeUnmount => "::before-unmount".into(),
92    }
93  }
94}