diff --git a/rearch/src/side_effects.rs b/rearch/src/side_effects.rs index cd96d6f..9c19877 100644 --- a/rearch/src/side_effects.rs +++ b/rearch/src/side_effects.rs @@ -89,43 +89,27 @@ where } } -// TODO -// /// Side effect that runs a callback whenever it changes and is dropped. -// /// Similar to `useEffect` from React. -// pub struct RunOnChangeEffect(Option); -// impl Default for RunOnChangeEffect { -// fn default() -> Self { -// Self(None) -// } -// } -// impl RunOnChangeEffect { -// #[must_use] -// pub fn new() -> Self { -// Self::default() -// } -// } -// impl Drop for RunOnChangeEffect { -// fn drop(&mut self) { -// if let Some(callback) = std::mem::take(&mut self.0) { -// callback(); -// } -// } -// } -// impl SideEffect for RunOnChangeEffect -// where -// F: FnOnce() + Send + 'static, -// { -// type Api<'a> = Box; - -// fn api(&mut self, _: Rebuilder) -> Self::Api<'_> { -// Box::new(move |new_effect| { -// if let Some(callback) = std::mem::take(&mut self.0) { -// callback(); -// } -// self.0 = Some(new_effect); -// }) -// } -// } +/// Side effect that runs a callback whenever it changes and is dropped. +/// Similar to `useEffect` from React. +pub fn run_on_change<'a, F>() -> impl SideEffect<'a, Api = impl FnMut(F) + 'a> +where + F: FnOnce() + Send + 'static, +{ + move |register: SideEffectRegistrar<'a>| { + let state = register.register(value(FunctionalDrop(None))); + // The old callback, if there is one, will be called when it is dropped, + // via the `*state = ...` assignment below + |callback| *state = FunctionalDrop(Some(callback)) + } +} +struct FunctionalDrop(Option); +impl Drop for FunctionalDrop { + fn drop(&mut self) { + if let Some(callback) = std::mem::take(&mut self.0) { + callback(); + } + } +} /// A thin wrapper around the state side effect that enables easy state persistence. ///