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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! use_previous hook for tracking previous values
//!
//! Useful for comparing current and previous values, detecting changes,
//! or implementing undo functionality.
//!
//! # Example
//!
//! ```rust,ignore
//! use rnk::prelude::*;
//!
//! fn app() -> Element {
//! let count = use_signal(|| 0);
//! let prev_count = use_previous(count.get());
//!
//! // Show change direction
//! let direction = if count.get() > prev_count.unwrap_or(0) {
//! "↑"
//! } else if count.get() < prev_count.unwrap_or(0) {
//! "↓"
//! } else {
//! "="
//! };
//!
//! Text::new(format!("Count: {} {}", count.get(), direction)).into_element()
//! }
//! ```
use crate::hooks::use_signal::use_signal;
/// Track the previous value of a variable
///
/// Returns `None` on the first render, then returns the previous value
/// on subsequent renders.
pub fn use_previous<T>(value: T) -> Option<T>
where
T: Clone + Send + Sync + 'static,
{
let current = use_signal(|| None::<T>);
let previous = use_signal(|| None::<T>);
// Get the previous value before updating
let result = previous.get();
// Update: previous = current, current = new value
previous.set(current.get());
current.set(Some(value));
result
}
/// Track whether a value has changed since last render
pub fn use_changed<T>(value: T) -> bool
where
T: Clone + PartialEq + Send + Sync + 'static,
{
let prev = use_previous(value.clone());
match prev {
Some(p) => p != value,
None => true, // First render counts as "changed"
}
}
/// Track the first render
pub fn use_is_first_render() -> bool {
let is_first = use_signal(|| true);
let result = is_first.get();
if result {
is_first.set(false);
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_use_previous_compiles() {
fn _test() {
let _prev = use_previous(42);
}
}
#[test]
fn test_use_changed_compiles() {
fn _test() {
let _changed = use_changed("test".to_string());
}
}
#[test]
fn test_use_is_first_render_compiles() {
fn _test() {
let _is_first = use_is_first_render();
}
}
}