我目前正在使用Dioxus生成一个动态更改图像轮询器的页面。
我现在想要实现的是使用max
函数来比较use_state
的结果,以防止数字低于1。
这是一个简单的应用程序:
use dioxus::{events::*, hooks::UseState, prelude::*};
use log::{info, LevelFilter};
use std::cmp::{max, Ordering};
impl PartialOrd for UseState<i32> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for UseState<i32> {
fn cmp(&self, other: &Self) -> Ordering {
self.x.cmp(&other.x)
}
}
/**
* Specify <link data-trunk rel="copy-dir" href="src/assets" />
* in the index.html to copy the files!!
*
* You'll see them in the dist directory!
*/
fn main() {
dioxus_logger::init(LevelFilter::Info).expect("failed to init logger");
dioxus::web::launch(app);
}
fn app(cx: Scope) -> Element {
let mut index = use_state(&cx, || 1);
let val = index.get() as &i32;
let num = 1 as i32;
let change_evt = move |evt: KeyboardEvent| match evt.key.as_str() {
"ArrowRight" => index += 1,
"ArrowLeft" => index = max(&num.try_into(), &val.try_into()),
_ => {}
};
let url = format!("/assets/manga/one_piece/1042/0{}.jpg", index);
cx.render(rsx!(img {
src: "{url}",
}
div {
class: "display",
onkeydown: change_evt,
button {
class: "but",
onclick: move |evt| {
println!("{evt:?}");
info!("{evt:?}");
},
"Press me!"
},
},
))
}
一开始我认为使用index.get()
会得到与max()
比较所需的i32
。
但是它抱怨并告诉我我需要为UseState{Integer}
实现PartialOrd
。
我目前正试图实现它。
这是我的cargo.toml
[package]
name = "rust-manga"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.2.4", features = ["web", "html"] }
dioxus-html = "0.2.1"
dioxus-logger = "0.3.0"
log = "0.4.17"
当为某些东西(如impl PartialOrd for UseState
)实现trait时,那么两个组件中至少有一个必须属于定义impl
的crate。但是PartialOrd
和UseState
都是在您的crate之外定义的,所以您不能这样做。
有两个选项:
- 一个属于你的板条箱的新类型,这样你就可以在上面实现特征:
struct MyUseState<T: 'static>(UseState<T>);
impl<T> PartialOrd for MyUseState<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
todo!();
}
}
缺点是您需要在自定义类型中包装使用dioxus::hooks::UseState
的实例,至少当您想比较事物时。
- 使用
UseState
提供的方法:
如果UseState
没有实现传递给std::cmp::max
所需的特征,我们必须获得内部值。它确实提供了多种方法来做到这一点,例如UseState::get()
,UseState::current()
或Deref
的实现。
我们可以做max(num, *index.get())
,其中.get()
得到一个&i32
,我们引用它来得到值。或max(num, **index)
,使用Deref
。
然而,我们仍然不能把它赋值给index
,因为i32
不能赋值给UseState
。
这就是UseState::modify()
的作用。它允许您就地修改值:
// Again, `.modify()` only gives a reference to the closure, which we have to derefence.
index.modify(|val| max(num, *val))