Resource, LazyCache, AutoMap
Resource
A Value that is loaded from somewhere else can in fact have 3 different states:
- Still loading
- Load failed and gave an error
- 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.