Rust/Yewで型を使って作業ミスを減らせた話

フロントエンド開発をしていると、特定のページに遷移する際にはmiddleware(特定の処理の前に割り込んで処理をする)が欲しいと思うことはよく有ります。
特に、ページ遷移するたびに、HTMLを表示したりAPIを叩いたりする前にユーザがログインしているかどうかをチェックしたい、というのは頻出のパターンですね。

Yewではそのようなmiddleware的な処理はpub children: Childrenというプロパティを持った構造体を用意してComponentに渡すようにすれば簡単に実現できます。

#[derive(Properties, PartialEq)]
pub struct Props {
    pub children: Children,
}

それはそれで良いのですが、実際に表示するページ側でそのmiddlewareを指定するのはあまりよろしくありません。
middlewareなので、各ページ的には「自分はそんな事に関心ないよ、自動でやっといてよね」となるのが普通です。

そこで、 yew-router を使っているなら以下のようにルーティング時点でmiddlewareを指定してあげることが出来ます。
なお、以下の<Secure>という部分が、私が作成したmiddleware相当のComponentです。

#[derive(Clone, Routable, PartialEq, Eq, Debug)]
pub enum Route {
    #[at("/")]
    Top,
    #[at("/index2")]
    Top2,
    #[at("/signin/")]
    Signin,
}

// これだと、ページが追加されていくと<Secure>をつけ忘れそう
pub fn switch(routes: Route) -> Html {
    match routes {
        Route::Top => html! {<Secure><index::Index /></Secure>},
        Route::Top2 => html! {<index2::Index />},
        Route::Signin => html! {<signin::Model />}
    }
}

しかし、コメントに書いている通り、手動でmiddlewareを指定しているので、本来は指定しないといけないのに書き忘れてしまった、ということが発生しそうです。
と言うより実際に上記のコードは私がミスした実例です。本当はRoute::Top2でも<Secure>を付けるべきところ、それを忘れていました。
そこで、以下のようにして直接middlewareを指定するのではなく、「どのようなmiddlewareが必要か」という情報を持たせるようにしてあげます。

#[derive(Clone, Routable, PartialEq, Eq, Debug)]
pub enum Route {
    #[at("/")]
    Top,
    #[at("/index2")]
    Top2,
    #[at("/signin/")]
    Signin,
}

// 以下のように書くことで、ページを追加する際に必ずSecureTypeの指定をしないとコンパイルエラーになるので、ミスでつけ忘れることがなくなる。
enum SecureType {
    Secure,
    NonSecure,
}

pub fn switch(routes: Route) -> Html {
    let (html: VNode, secure_type: SecureType) = match routes {
        Route::Top => (html! {<index::Index />}, SecureType::Secure),
        Route::Top2 => (html!{<index2::Index />}, SecureType::Secure),
        Route::Signin => (html! {<signin::Model />}, SecureType::NonSecure)
    };
    match (html, secure_type) {
        (html, SecureType::Secure) => html!{<Secure>{html}</Secure>},
        (html, _)  => html
    }
}

このように書けば、必要なmiddlewareの情報をまとめたenumの値を書き忘れたらコンパイルエラーになるので、「必要だったのに書き忘れた」というミスを型を使って防止することが出来ます。

公開日:2023/01/26

Rust Yew

About me

ドイツの現地企業でWeb Developer/System Administratorとして働いているアラフォーおじさんです。

プログラミングとかコンピュータに関する事がメインですが、日常的なメモとか雑多なことも書きます。

Links :
目次