Skip to main content

basic/
basic.rs

1use gpui::{
2    App, Application, Bounds, Context, Window, WindowBounds, WindowOptions, div, prelude::*, px,
3    rgb, size,
4};
5use gpui_hooks::{HookedRender, hook_element};
6// 按需导入需要的 hook traits
7use gpui_hooks::hooks::{UseCallbackHook, UseEffectHook, UseMemoHook, UseRefHook, UseStateHook};
8
9#[hook_element]
10struct CounterApp {}
11
12impl HookedRender for CounterApp {
13    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
14        // useState - 管理计数器状态
15        let (count, set_count) = self.use_state(|| 0i32);
16
17        // useMemo - 计算双倍值
18        let count_val = count();
19        let doubled = self.use_memo(|| count_val * 2, [count_val]);
20
21        // useEffect - 副作用,当count变化时执行
22        self.use_effect(
23            || {
24                println!("Effect: count changed to {}", count_val);
25                // 返回可选的清理函数
26                Some(|| {
27                    println!("Effect cleanup: previous effect is being cleaned up");
28                })
29            },
30            [count_val],
31        );
32
33        // useRef - 创建一个可变引用,用于存储上一次的值
34        let prev_count_ref = self.use_ref(|| 0i32);
35        let current_count = count_val;
36
37        // 更新引用值
38        if current_count != *prev_count_ref.borrow() {
39            *prev_count_ref.borrow_mut() = current_count;
40        }
41
42        // useCallback - 创建一个记忆化的回调函数
43        let handle_increment = self.use_callback(
44            || {
45                let count_val = current_count;
46                Box::new(move || {
47                    println!("Callback executed with count: {}", count_val);
48                    count_val + 1
49                }) as Box<dyn Fn() -> i32>
50            },
51            [current_count],
52        );
53
54        div()
55            .flex()
56            .flex_col()
57            .gap_3()
58            .bg(rgb(0x2d2d2d))
59            .size(px(500.0))
60            .justify_center()
61            .items_center()
62            .shadow_lg()
63            .border_1()
64            .border_color(rgb(0x555555))
65            .text_xl()
66            .text_color(rgb(0xffffff))
67            // 计数器显示
68            .child(format!("Count: {}", count()))
69            // 双倍值显示(useMemo)
70            .child(format!("Doubled (useMemo): {}", doubled()))
71            // useRef显示
72            .child(format!(
73                "Previous count (useRef): {}",
74                *prev_count_ref.borrow()
75            ))
76            // 操作说明
77            .child("Check console for effect and callback logs")
78            .child(div().child("click me").id("counter").on_click(cx.listener(
79                move |_this, _, _window, cx| {
80                    set_count(count() + 1);
81                    cx.notify();
82                },
83            )))
84            // useCallback测试按钮
85            .child(
86                div()
87                    .child("test callback")
88                    .id("callback-test")
89                    .on_click(cx.listener(move |_this, _, _window, _cx| {
90                        let result = handle_increment();
91                        println!("Callback returned: {}", result);
92                    })),
93            )
94    }
95}
96
97fn main() {
98    Application::new().run(|cx: &mut App| {
99        let bounds = Bounds::centered(None, size(px(500.), px(500.0)), cx);
100        cx.open_window(
101            WindowOptions {
102                window_bounds: Some(WindowBounds::Windowed(bounds)),
103                ..Default::default()
104            },
105            |_, cx| {
106                cx.new(|_| CounterApp {
107                    ..Default::default()
108                })
109            },
110        )
111        .unwrap();
112    });
113}