Skip to content

JoschuaL/dioxus-mvu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MVU pattern for Dioxus, heavily inspiret by F# Feliz use_elmish hook.

Predictable State management with no Suprises

#[derive(Clone)]
struct Model {
    count: i32,
}

enum Msg {
    ADD,
    SUB,
    RESET,
}

fn init() -> Model {
    Model { count: 0 }
}

fn update(msg: Msg, state: Model) -> Model {
    match msg {
        Msg::ADD => Model {
            count: state.count + 1,
        },
        Msg::SUB => Model {
            count: state.count - 1,
        },
        Msg::RESET => Model { count: 0 },
    }
}

#[component]
fn Counter() -> Element {
    let elm = use_elmish_simple(init, update);
    let model = elm.model();

    rsx! {
        div {
            id: "hero",
            button {
                onclick: move |_| {elm.dispatch(Msg::SUB)},
                "-"
            }
            "{model.count}"
            button {
                onclick: move |_| {elm.dispatch(Msg::ADD)},
                "+"
            }
            button {
                onclick: move |_| {elm.dispatch(Msg::RESET)},
                "RESET"
            }
        }
    }
}

Simple Representation for async command flows

#[component]
fn BreedPic(breed: ReadOnlySignal<String>) -> Element {

    #[derive(Default, Debug, Clone)]
    struct Model {
        dog: Option<DogApi>,
        error: Option<String>
    }

    enum Msg {
        GettingDog(String),
        GotDog(DogApi),
        GetDogError(reqwest::Error),
    }

    let get_dog = async move |breed: String| -> Result<DogApi, reqwest::Error> {
        reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
            .await?
            .json::<DogApi>()
            .await
    };

    let update = move |msg: Msg, state: Model| match msg {
        Msg::GettingDog(breed) => (
            Model { dog: None, ..state },
            Cmd::of_async_res(move || get_dog(breed), Msg::GotDog, Msg::GetDogError),
        ),
        Msg::GotDog(dog) => (Model { dog: Some(dog), ..state }, Cmd::none()),
        Msg::GetDogError(e) => (Model {dog: None, error: format!("error getting dogs: {e}")}, Cmd::none()),
    };

    let elmish = use_elmish_with_cmd(Model::default, update, move || {
        Cmd::of_msg(Msg::GettingNewDog(breed()))
    });
    let model = elmish.model();

    if let Some(dog) = model.dog {
        rsx! {
            div {
                button { onclick: move |_| elmish.dispatch(Msg::GettingNewDog(breed())), padding: "5px", background_color: "gray", color: "white", border_radius: "5px", "Click to fetch another doggo" }
                img { max_width: "500px", max_height: "500px", src: "{dog.message}" }
            }
        }
    } else if let Some(err) = model.error {
        rsx!(model.error)
    } else {
        rsx!("loading doggo...")
    }
    // This resource will restart whenever the breed changes
}

About

MVU pattern for Dioxus, heavily inspiret by F# Feliz use_elmish hook

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages