123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- mod handle;
- mod owned;
- pub use handle::*;
- pub use owned::*;
- use dioxus_core::prelude::*;
- use std::{
- cell::{Cell, RefCell},
- rc::Rc,
- };
- /// Store state between component renders!
- ///
- /// ## Dioxus equivalent of useState, designed for Rust
- ///
- /// The Dioxus version of `useState` for state management inside components. It allows you to ergonomically store and
- /// modify state between component renders. When the state is updated, the component will re-render.
- ///
- /// Dioxus' use_state basically wraps a RefCell with helper methods and integrates it with the VirtualDOM update system.
- ///
- /// [`use_state`] exposes a few helper methods to modify the underlying state:
- /// - `.set(new)` allows you to override the "work in progress" value with a new value
- /// - `.get_mut()` allows you to modify the WIP value
- /// - `.get_wip()` allows you to access the WIP value
- /// - `.deref()` provides the previous value (often done implicitly, though a manual dereference with `*` might be required)
- ///
- /// Additionally, a ton of std::ops traits are implemented for the `UseState` wrapper, meaning any mutative type operations
- /// will automatically be called on the WIP value.
- ///
- /// ## Combinators
- ///
- /// On top of the methods to set/get state, `use_state` also supports fancy combinators to extend its functionality:
- /// - `.classic()` and `.split()` convert the hook into the classic React-style hook
- /// ```rust
- /// let (state, set_state) = use_state(&cx, || 10).split()
- /// ```
- ///
- ///
- /// Usage:
- ///
- /// ```ignore
- /// const Example: Component = |cx| {
- /// let counter = use_state(&cx, || 0);
- ///
- /// cx.render(rsx! {
- /// div {
- /// h1 { "Counter: {counter}" }
- /// button { onclick: move |_| counter += 1, "Increment" }
- /// button { onclick: move |_| counter -= 1, "Decrement" }
- /// }
- /// ))
- /// }
- /// ```
- pub fn use_state<'a, T: 'static>(
- cx: &'a ScopeState,
- initial_state_fn: impl FnOnce() -> T,
- ) -> UseState<'a, T> {
- let hook = cx.use_hook(move |_| UseStateOwned {
- current_val: Rc::new(initial_state_fn()),
- update_callback: cx.schedule_update(),
- wip: Rc::new(RefCell::new(None)),
- update_scheuled: Cell::new(false),
- });
- hook.update_scheuled.set(false);
- let mut new_val = hook.wip.borrow_mut();
- if new_val.is_some() {
- // if there's only one reference (weak or otherwise), we can just swap the values
- if let Some(val) = Rc::get_mut(&mut hook.current_val) {
- *val = new_val.take().unwrap();
- } else {
- hook.current_val = Rc::new(new_val.take().unwrap());
- }
- }
- UseState(hook)
- }
|