Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 63 additions & 5 deletions packages/yew/src/functional/hooks/use_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,74 @@ use std::rc::Rc;
use crate::functional::{hook, use_state, Hook, HookContext};
use crate::NodeRef;

struct UseMutRef<F> {
struct UseRef<F> {
init_fn: F,
}

impl<T: 'static, F: FnOnce() -> T> Hook for UseMutRef<F> {
type Output = Rc<RefCell<T>>;
impl<T: 'static, F: FnOnce() -> T> Hook for UseRef<F> {
type Output = Rc<T>;

fn run(self, ctx: &mut HookContext) -> Self::Output {
ctx.next_state(|_| RefCell::new((self.init_fn)()))
ctx.next_state(|_| (self.init_fn)())
}
}

/// This hook is used for obtaining a reference to a stateful value.
/// Its state persists across renders.
///
/// Mutation must be done via interior mutability, such as `Cell` or `RefCell`.
///
/// It is important to note that you do not get notified of state changes.
/// If you need the component to be re-rendered on state change, consider using
/// [`use_state`](super::use_state()).
///
/// # Example
/// ```rust
/// use std::cell::Cell;
/// use std::ops::{Deref, DerefMut};
/// use std::rc::Rc;
///
/// use web_sys::HtmlInputElement;
/// use yew::prelude::*;
///
/// #[function_component(UseRef)]
/// fn ref_hook() -> Html {
/// let message = use_state(|| "".to_string());
/// let message_count = use_ref(|| Cell::new(0));
///
/// let onclick = Callback::from(move |e| {
/// let window = gloo::utils::window();
///
/// if message_count.get() > 3 {
/// window.alert_with_message("Message limit reached");
/// } else {
/// message_count.set(message_count.get() + 1);
/// window.alert_with_message("Message sent");
/// }
/// });
///
/// let onchange = {
/// let message = message.clone();
/// Callback::from(move |e: Event| {
/// let input: HtmlInputElement = e.target_unchecked_into();
/// message.set(input.value())
/// })
/// };
///
/// html! {
/// <div>
/// <input {onchange} value={(*message).clone()} />
/// <button {onclick}>{ "Send" }</button>
/// </div>
/// }
/// }
pub fn use_ref<T: 'static, F>(init_fn: F) -> impl Hook<Output = Rc<T>>
where
F: FnOnce() -> T,
{
UseRef { init_fn }
}

/// This hook is used for obtaining a mutable reference to a stateful value.
/// Its state persists across renders.
///
Expand Down Expand Up @@ -68,7 +124,9 @@ pub fn use_mut_ref<T: 'static, F>(init_fn: F) -> impl Hook<Output = Rc<RefCell<T
where
F: FnOnce() -> T,
{
UseMutRef { init_fn }
UseRef {
init_fn: || RefCell::new(init_fn()),
}
}

/// This hook is used for obtaining a [`NodeRef`].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Yew comes with the following predefined Hooks:
- `use_state_eq`
- `use_memo`
- `use_callback`
- `use_ref`
- `use_mut_ref`
- `use_node_ref`
- `use_reducer`
Expand Down