Resource, LazyCache, AutoMap

Resource

A Value that is loaded from somewhere else can in fact have 3 different states:

  1. Still loading
  2. Load failed and gave an error
  3. Load succeeded and gave proper result

This situation is represented by the Resource struct. Note, that you still need to wrap Resource with Value to keep it reactive!

    use vertigo::{bind, dom, Resource, Value};

    let my_value = Value::new(Resource::Loading);

    let set_ready = bind!(my_value, |_| my_value.set(Resource::Ready("OK".to_string())));

    let set_error = bind!(my_value, |_| my_value
        .set(Resource::Error("Error!".to_string())));

    let value_rendered = my_value.render_value(|value| {
        dom! {
            <p>{
                match value {
                    Resource::Loading => "Still loading".to_string(),
                    Resource::Ready(val) => format!("Ready: {val}"),
                    Resource::Error(err) => format!("Error: {err}"),
                }
            }</p>
        }
    });

    dom! {
        <div>
            <p>"Current value: " {value_rendered}</p>
            <button on_click={set_ready} value="Set ready" />
            <button on_click={set_error} value="Set error" />
        </div>
    }

LazyCache

Even more handy way when loading a value from the internet is to use LazyCache . It caches the result for defined amount of time and refreshes upon expiry.

It can be created out of a RequestBuilder and inherits the ttl setting from it.

    use vertigo::{AutoJsJson, RequestBuilder};

    #[derive(AutoJsJson, PartialEq, Clone)]
    pub struct Model {
        id: i32,
        name: String,
    }

    let posts = RequestBuilder::get("https://some.api/posts")
        .ttl_seconds(300)
        .lazy_cache(|status, body| {
            if status == 200 {
                Some(body.into::<Vec<Model>>())
            } else {
                None
            }
        });

Internally it hold ApiResponse struct, which is a Resource<T> + expiry time. You just need to provide a handler which gets HTTP status + body, which you need to convert to T or error.

AutoMap

If your request depends on some parameter, for example a slug, you can use AutoMap to keep LazyCache value for every requested parameter set.

    use vertigo::{AutoJsJson, AutoMap, RequestBuilder};

    #[derive(AutoJsJson, PartialEq, Clone)]
    pub struct Model {
        id: i32,
        name: String,
    }

    let posts = AutoMap::new(|_myself, slug: &String| {
        let url = format!("https://some.api/posts/{slug}");
        RequestBuilder::get(url)
            .ttl_seconds(300)
            .lazy_cache(|status, body| {
                if status == 200 {
                    Some(body.into::<Model>())
                } else {
                    None
                }
            })
    });

Constructor of AutoMap takes a generator which converts parameter to value. It also takes the AutoMap itself just in case, but can be safely ignored.