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

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

我的代码如下:

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>
    }
}

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

rust 复制代码
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,

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

rust 复制代码
fn set(&self, value: T);
fn deref(&self) -> &Self::Target;

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

1. 赋初值

给state赋初值的是FnOnce,它是Rust中的一个trait(特征),用于表示可以调用一次的闭包(Closure)。

因此,上面的代码也可以这样写:

rust 复制代码
    let init_data = || false;
    let modalVisible = use_state(init_data);

2. 状态读取

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

rust 复制代码
<Modal1 show={*modalVisible} {onclose}/>

这个*号可以用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来获取它的值,例如\<TableComponent data={(*data).clone()}/>

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

3. 状态修改

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

rust 复制代码
    let onclick = {
        let modalVisible1 = modalVisible.clone();
        Callback::from(move |_| modalVisible1.set(!*modalVisible1))
    };
    let onclose = {
        let modalVisible1 = modalVisible.clone();
        Callback::from(move |_| modalVisible1.set(!*modalVisible1))
    };

我们在调用set方法之前,将modalVisible对象克隆了一份,否者会报所有权相关的错误。

另外,onclick和onclose这两段代码看似一样,但这两段代码在使用时有类型推断,因此如果复用onclick变量或者onclose变量,都会报类型错误。因此,还是要独立写成两份。这在ReactJs中是完全没有的事儿啊。

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

相关推荐
Avan_菜菜21 分钟前
AI 能写代码了,为什么我反而开始要求它先写文档?
前端·github·ai编程
JieE2124 小时前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2124 小时前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
爱勇宝4 小时前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
IT_陈寒8 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen8 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
Larcher8 小时前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
默_笙8 小时前
🃏 JS 只有 8 种数据类型,但我花了 2 天才搞懂 null 和 undefined 的区别
javascript
牧艺8 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
jump_jump9 小时前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化