use std::borrow::Borrow;
use std::rc::Rc;
use super::use_mut_ref;
use crate::functional::hook;
#[hook]
pub(crate) fn use_memo_base<T, F, D, K>(f: F, deps: D) -> Rc<T>
where
T: 'static,
F: FnOnce(D) -> (T, K),
K: 'static + Borrow<D>,
D: PartialEq,
{
struct MemoState<T, K> {
memo_key: K,
result: Rc<T>,
}
let state = use_mut_ref(|| -> Option<MemoState<T, K>> { None });
let mut state = state.borrow_mut();
match &*state {
Some(existing) if existing.memo_key.borrow() != &deps => {
*state = None;
}
_ => {}
};
let state = state.get_or_insert_with(|| {
let (result, memo_key) = f(deps);
let result = Rc::new(result);
MemoState { result, memo_key }
});
state.result.clone()
}
#[hook]
pub fn use_memo<T, F, D>(deps: D, f: F) -> Rc<T>
where
T: 'static,
F: FnOnce(&D) -> T,
D: 'static + PartialEq,
{
use_memo_base(|d| (f(&d), d), deps)
}