🐷

dioxusのwebを利用してIntroductionのカウンターを作ってみる

2022/02/04に公開

Introductionにあるチュートリアルを触ってみます。

rustの環境を用意して、dioxusを追加します。
インストールなどは、ここをみるとよさそうです。

cargo add dioxus --features web

Introductionにあるコードをそのまま利用します。

use dioxus::prelude::*;

fn main() {
    dioxus::web::launch(App);
}

fn App(cx: Scope) -> Element {
    let mut count = use_state(&cx, || 0);

    cx.render(rsx!(
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| count += 1, "Up high!" }
        button { onclick: move |_| count -= 1, "Down low!" }
    ))
};

trunk serve で起動しようとしますが、

エラーの詳細
error: expected item, found `;`
  --> src/main.rs:17:2
   |
17 | };
   |  ^ help: remove this semicolon

error[E0277]: `(&{integer}, &UseState<{integer}>)` doesn't implement `std::fmt::Display`
  --> src/main.rs:12:15
   |
12 |       cx.render(rsx!(
   |  _______________^
13 | |         h1 { "High-Five counter: {count}" }
14 | |         button { onclick: move |_| count += 1, "Up high!" }
15 | |         button { onclick: move |_| count -= 1, "Down low!" }
16 | |     ))
   | |_____^ `(&{integer}, &UseState<{integer}>)` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `(&{integer}, &UseState<{integer}>)`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0368]: binary assignment operation `+=` cannot be applied to type `(&{integer}, &UseState<{integer}>)`
  --> src/main.rs:14:36
   |
14 |         button { onclick: move |_| count += 1, "Up high!" }
   |                                    -----^^^^^
   |                                    |
   |                                    cannot use `+=` on type `(&{integer}, &UseState<{integer}>)`

error[E0368]: binary assignment operation `-=` cannot be applied to type `(&{integer}, &UseState<{integer}>)`
  --> src/main.rs:15:36
   |
15 |         button { onclick: move |_| count -= 1, "Down low!" }
   |                                    -----^^^^^
   |                                    |
   |                                    cannot use `-=` on type `(&{integer}, &UseState<{integer}>)`

Some errors have detailed explanations: E0277, E0368.
For more information about an error, try `rustc --explain E0277`.

のようなエラーが出てしまいます。

その型では演算できないよって言われているので、ちょっと確認しましたが、
use_stateで返却されているあたいの型は、integerではないようです。

型を確認すると、現在の値と更新するための関数がタプル型で返却されています。
https://github.com/DioxusLabs/dioxus/blob/e02dfc3324fdb808f6390d2d6942fb727220a329/packages/hooks/src/usestate.rs#L31-L34

エラーを解消して動作が確認できる状態になったコードです。

use dioxus::prelude::*;

fn main() {
    dioxus::web::launch(App);
}

fn App(cx: Scope) -> Element {
    let (count, set_count) = use_state(&cx, || 0);
    ;
    cx.render(rsx!{
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| set_count(count + 1), "Up high!" }
        button { onclick: move |_| set_count(count - 1), "Down low!" }
    })
}

このCommitで大きく変わっているようでした。
https://github.com/DioxusLabs/dioxus/commit/a8952a9ee8d8831fa911cef4e7035293c3a9f88b#diff-a946ff8854b3c5adae720cdb9419e97cd4f5a3f9c0060bc7502973ed09211c67

In general, Dioxus and React share many functional similarities. If this guide is lacking in any general concept or an error message is confusing, React's documentation might be more helpful. We are dedicated to providing a familiar toolkit for UI in Rust, so we've chosen to follow in the footsteps of popular UI frameworks (React, Redux, etc). If you know React, then you already know Dioxus. If you don't know either, this guide will still help you!

公式にも記載されていますが、Reactとの類似点が多くあるといっているので、エラーが出たらReactを思い出せば解決できるかもしれません。

exampleもたくさん公開されているので、こちらも参考にするとよさそうです。
https://github.com/DioxusLabs/dioxus/tree/master/examples

以下のレポジトリにも今回のコードを格納しておきます。
https://github.com/activeguild/dioxusex/blob/master/src/main.rs

もう少し踏み込んだ話は、mizchiさんがまとめてくださっているので、そちらを参照ください。
https://zenn.dev/mizchi/scraps/449f0591e2cee9

Discussion