mod use_context;
mod use_effect;
mod use_reducer;
mod use_ref;
mod use_state;
pub use use_context::*;
pub use use_effect::*;
pub use use_reducer::*;
pub use use_ref::*;
pub use use_state::*;
use crate::functional::{HookUpdater, CURRENT_HOOK};
use std::cell::RefCell;
use std::ops::DerefMut;
use std::rc::Rc;
pub fn use_hook<InternalHook: 'static, Output, Tear: FnOnce(&mut InternalHook) + 'static>(
initializer: impl FnOnce() -> InternalHook,
runner: impl FnOnce(&mut InternalHook, HookUpdater) -> Output,
destructor: Tear,
) -> Output {
if !CURRENT_HOOK.is_set() {
panic!("Hooks can only be used in the scope of a function component");
}
let updater = CURRENT_HOOK.with(|hook_state| {
let hook_pos = hook_state.counter;
hook_state.counter += 1;
if hook_pos >= hook_state.hooks.len() {
let initial_state = Rc::new(RefCell::new(initializer()));
hook_state.hooks.push(initial_state.clone());
hook_state.destroy_listeners.push(Box::new(move || {
destructor(initial_state.borrow_mut().deref_mut());
}));
}
let hook = hook_state
.hooks
.get(hook_pos)
.expect("Not the same number of hooks. Hooks must not be called conditionally")
.clone();
HookUpdater {
hook,
process_message: hook_state.process_message.clone(),
}
});
let mut hook = updater.hook.borrow_mut();
let hook: &mut InternalHook = hook
.downcast_mut()
.expect("Incompatible hook type. Hooks must always be called in the same order");
runner(hook, updater.clone())
}