freya_core/lifecycle/reactive.rs
1use crate::prelude::{
2 State,
3 use_state,
4};
5
6/// Convert a borrowed value (`&T`) into a component-scoped [`State<T>`].
7///
8/// Useful when a component owns fields (props) and you need a reactive `State<T>` that can
9/// be passed to hooks, effects, or child components without cloning repeatedly.
10///
11/// The returned `State<T>` is initialized by cloning the provided `value`. On subsequent
12/// renders the internal state will be updated to follow `value` whenever it changes
13/// (using `PartialEq` to avoid unnecessary updates).
14///
15/// Example
16/// ```rust,no_run
17/// # use freya::prelude::*;
18/// #[derive(Clone, PartialEq)]
19/// struct Config {
20/// value: i32,
21/// }
22///
23/// #[derive(PartialEq)]
24/// struct MyComponent {
25/// config: Config,
26/// }
27///
28/// impl Component for MyComponent {
29/// fn render(&self) -> impl IntoElement {
30/// let config = use_reactive(&self.config);
31///
32/// use_side_effect(move || {
33/// // `.read()` subscribes the effect to changes of `config`
34/// let config = config.read();
35/// println!("config value: {}", config.value);
36/// });
37///
38/// rect()
39/// }
40/// }
41/// ```
42///
43/// Notes:
44/// - Call `use_reactive` at the top level of your component's `render` method like other hooks.
45/// - The hook avoids extra cloning by only setting the internal state when `value` differs.
46pub fn use_reactive<T: 'static + Clone + PartialEq>(value: &T) -> State<T> {
47 let mut state = use_state(|| value.clone());
48
49 if &*state.peek() != value {
50 state.set(value.clone());
51 }
52 state
53}