10_state_explained/
10_state_explained.rs1use crossterm::event::KeyCode;
9use telex::prelude::*;
10use telex::Color;
11
12telex::require_api!(0, 2);
13
14fn main() {
15 telex::run_with_theme(App, telex::theme::Theme::nord()).unwrap();
16}
17
18struct App;
19
20impl Component for App {
21 fn render(&self, cx: Scope) -> View {
22 let count = state!(cx, || 0i32);
23 let show_help = state!(cx, || false);
24
25 cx.use_command(
27 KeyBinding::key(KeyCode::F(1)),
28 with!(show_help => move || show_help.update(|v| *v = !*v)),
29 );
30
31 let count_for_increment = count.clone();
33 let count_for_decrement = count.clone();
34 let count_for_reset = count.clone();
35
36 let increment = move || {
37 let current = count_for_increment.get();
38 count_for_increment.set(current + 1);
39 };
40
41 let decrement = move || {
42 let current = count_for_decrement.get();
43 count_for_decrement.set(current - 1);
44 };
45
46 let reset = move || {
47 count_for_reset.set(0);
48 };
49
50 let current_value = count.get();
51
52 let _always_called_1 = state!(cx, || "hook 1");
54 let _always_called_2 = state!(cx, || "hook 2");
55
56 View::vstack()
57 .spacing(1)
58 .child(
59 View::styled_text("State Explained")
60 .color(Color::Cyan)
61 .bold()
62 .build(),
63 )
64 .child(
65 View::boxed()
66 .border(true)
67 .padding(1)
68 .child(
69 View::vstack()
70 .child(View::styled_text("The Mental Model:").bold().build())
71 .child(View::gap(1))
72 .child(View::text(" State<T> is a HANDLE, not data"))
73 .child(View::text(" clone() copies the handle, not the data"))
74 .child(View::text(" All handles point to ONE value"))
75 .child(View::gap(1))
76 .child(View::text(" count ──────┐"))
77 .child(View::text(" ├──► i32: 0 (shared!)"))
78 .child(View::text(" count2 ─────┘"))
79 .build(),
80 )
81 .build(),
82 )
83 .child(
84 View::hstack()
85 .spacing(1)
86 .child(View::text("Current value:"))
87 .child(
88 View::styled_text(format!("{}", current_value))
89 .color(Color::Yellow)
90 .bold()
91 .build(),
92 )
93 .build(),
94 )
95 .child(
96 View::hstack()
97 .spacing(1)
98 .child(View::button().label(" - ").on_press(decrement).build())
99 .child(View::button().label(" + ").on_press(increment).build())
100 .child(View::button().label("Reset").on_press(reset).build())
101 .build(),
102 )
103 .child(
104 View::styled_text("All three buttons modify the SAME underlying i32")
105 .dim()
106 .build(),
107 )
108 .child(View::gap(1))
109 .child(
110 View::styled_text("Tab navigate • F1 help • Ctrl+Q quit")
111 .dim()
112 .build(),
113 )
114 .child(
115 View::modal()
116 .visible(show_help.get())
117 .title("Example 10: State Explained")
118 .on_dismiss(with!(show_help => move || show_help.set(false)))
119 .child(
120 View::vstack()
121 .child(View::styled_text("What you're seeing").bold().build())
122 .child(View::text("• State<T> as a handle/pointer concept"))
123 .child(View::text("• Multiple closures sharing one value"))
124 .child(View::text("• Visual diagram of the mental model"))
125 .child(View::gap(1))
126 .child(View::styled_text("Key concepts").bold().build())
127 .child(View::text("• clone() copies handle, not data"))
128 .child(View::text("• All handles point to same underlying value"))
129 .child(View::text(
130 "• Hooks must be called in same order every render",
131 ))
132 .child(View::gap(1))
133 .child(View::styled_text("Important rule").bold().build())
134 .child(View::text("• NEVER put use_state inside an if block"))
135 .child(View::text("• Use with!() macro to simplify cloning"))
136 .child(View::gap(1))
137 .child(View::styled_text("Next up").bold().build())
138 .child(View::text("→ 11_checkbox: toggle controls"))
139 .child(View::gap(1))
140 .child(View::styled_text("Press Escape to close").dim().build())
141 .build(),
142 )
143 .build(),
144 )
145 .build()
146 }
147}