• [2023.09.12]: Yew应用开发的第一个hook--use_state


    Yew的SSR模式推荐使用function_component组件,并且在function_component中使用hooks。其中,我使用到的第一个hook是use_state。use_state的设计意图与React中的useState非常相似,都是为了保存并修改当前的状态。然而,由于Yew是用Rust语言实现的,所以在具体使用上还是有一些差异的。

    我的代码如下:

    mod components;
    mod models;
    use components::TableComponent;
    use models::TableRow;
    use yew::prelude::*;
    
    #[function_component]
    fn Content() -> HtmlResult {
        let modalVisible = use_state(|| false);
    
        let onclick = {
            let modalVisible1 = modalVisible.clone();
            Callback::from(move |_| modalVisible1.set(!*modalVisible1))
        };
        let onclose = {
            let modalVisible1 = modalVisible.clone();
            Callback::from(move |_| modalVisible1.set(!*modalVisible1))
        };
    
        Ok(html! {
            <div class="column">
                <div class="section row content-end">
                    <Button text={"新建"} {onclick} />
                </div>
                <TableComponent data={data}/>
                <Modal1 show={*modalVisible} {onclose}/>
            </div>
        })
    
    }
    
    #[function_component]
    pub fn App() -> Html {
        let fallback = html! {<div>{"Loading..."}</div>};
    
        html! {
            <Suspense {fallback}>
                <Content />
            </Suspense>
        }
    }
    
    • 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

    在讨论差异前,首先看use_state的声明

    pub fn use_state<'hook, T, F>(
        init_fn: F
    ) -> impl 'hook + Hook<Output = UseStateHandle<T>>
    where
        T: 'static,
        F: FnOnce() -> T,
        T: 'hook,
        F: 'hook,
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    UseStateHandle的方法比较多,关于取值和赋值的方法如下:

    fn set(&self, value: T);
    fn deref(&self) -> &Self::Target;
    
    • 1
    • 2

    关于差异,限于我的使用经验,我这里先提出3个地方。

    1. 赋初值

    给state赋初值的是FnOnce,它是Rust中的一个trait(特征),用于表示可以调用一次的闭包(Closure)。
    因此,上面的代码也可以这样写:

        let init_data = || false;
        let modalVisible = use_state(init_data);
    
    • 1
    • 2

    2. 状态读取

    在上面的代码中,读取状态的代码如下:

    <Modal1 show={*modalVisible} {onclose}/>
    
    • 1

    这个*号可以用deref()的方法来代替,这是因为UseStateHandle实现了core::ops::Deref trait。显然*使用更加方便,而且还不用显示引入core::ops::Deref;

    需要注意的是,我们这里使用的是bool值,这种数据类型自动实现了Copy trait,因此,我们可以直接通过*modalVisible来使用它的值。如果是一个自定义的struct,那么这个struct要么也实现了Copy trait,要么实现了Clone trait。一般来说,我们可以直接通过#[derive(Clone)]来实现Clone trait,而实现Copy trait 则会比较麻烦。
    因此,大多数情况,我们都会为struct实现Clone trait。所以,如果state是自定义的struct类型,我们要通过clone来获取它的值,例如\

    在Reactjs中,直接通过解构useState的结果就可以拿到状态数据,相对简单得多呐。

    3. 状态修改

    使用set(&self, value: T) 方法来实现类似于React.js中的setXXX行为。但这里还是要提到clone()

        let onclick = {
            let modalVisible1 = modalVisible.clone();
            Callback::from(move |_| modalVisible1.set(!*modalVisible1))
        };
        let onclose = {
            let modalVisible1 = modalVisible.clone();
            Callback::from(move |_| modalVisible1.set(!*modalVisible1))
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们在调用set方法之前,将modalVisible对象克隆了一份,否者会报所有权相关的错误。
    另外,onclick和onclose这两段代码看似一样,但这两段代码在使用时有类型推断,因此如果复用onclick变量或者onclose变量,都会报类型错误。因此,还是要独立写成两份。这在ReactJs中是完全没有的事儿啊。

    上面的内容比较粗浅。有不对的地方还希望大家多多指教。

  • 相关阅读:
    Etcd 构建高可用Etcd集群
    emqx创建规则引擎写入tDengine
    python 碰到问题
    create_generated_clock invert preinvert shift_edge是否符合设计真实状态很重要【示例2】
    monorepo实践:yarn workspace + vite + typescript + react
    NOIP2011-2018提高组解题报告
    微服务项目调用外部接口
    神经网络阈值是什么意思,神经网络阈值如何确定
    MySQL 性能优化
    全国各省产业结构协调-高级化、合理化指标(2000-2020年)
  • 原文地址:https://blog.csdn.net/firefox1/article/details/132833582