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
use js_sys::Function;
use wasm_bindgen::{prelude::Closure, JsCast, JsValue, UnwrapThrowExt};
use crate::react_bindings;
/// Allows access to the transition state.
#[derive(Debug, Clone)]
pub struct Transition {
is_pending: bool,
start_transition: Function,
}
impl Transition {
/// Returns whether the transition is active or not.
pub fn is_pending(&self) -> bool {
self.is_pending
}
/// Marks the updates in the given closure as transitions.
pub fn start(&mut self, f: impl FnOnce() + 'static) {
self
.start_transition
.call1(&JsValue::NULL, &Closure::once_into_js(f))
.expect_throw("unable to call start function");
}
}
/// Returns a stateful value for the pending state of the transition, and a
/// function to start it.
///
/// # Example
///
/// ```
/// # use wasm_react::{*, hooks::*};
/// #
/// # fn render() -> VNode {
/// let count = use_state(|| 0);
/// let transition = use_transition();
///
/// h!(div).build((
/// transition.is_pending().then(||
/// h!(div).build("Loading…")
/// ),
/// h!(button).on_click(&callback!(clone(mut transition), move |_| {
/// let mut count = count.clone();
///
/// transition.start(move || {
/// count.set(|c| c + 1);
/// });
/// })).build(()),
/// ))
/// # }
/// ```
pub fn use_transition() -> Transition {
let result = react_bindings::use_transition();
let is_pending = result
.get(0)
.as_bool()
.expect_throw("unable to read pending state from transition");
let start_transition = result
.get(1)
.dyn_into::<Function>()
.expect_throw("unable to read start function from transition");
Transition {
is_pending,
start_transition,
}
}