State Management
What is state management?
When executing an application, we can't store and retrieve values from frame to frame.
To actually store and access data between frames, we need a global application state structure.
In Maycoon, we can use #[derive(State)]
to automatically implement the State
trait for a struct.
#![allow(unused)] fn main() { #[derive(State)] struct MyState { my_data: MyDataType, } }
Managing a state.
There are multiple implementation for handling application states among different frameworks, but Maycoon uses its own kind of state management system.
Every value inside a widget (such as a text) should be wrapped inside a Val<T>
where T is the data type.
The Val<T>
itself is an enum and has two variants:
Val::State { factory, .. }
for state dependent values.Val::Val(T)
for state independent values.
State dependent values
State dependent means, you need access to the global application State
to produce a value.
This might be a simple field (state.value
) or a more complex operation (e.g. retrieving something from a database).
To wrap a state dependent value inside a State
you can use the Val::new_state()
function, but we recommend using the val!()
macro to create a state value like this:
#![allow(unused)] fn main() { // simple val!(|state: MyState| state.counter); // more complex val!(|state: MyState| { let value = state.input; let life = meaning_of_life(value); return if life.is_some() { "life has meaning".to_string() } else { "life has no meaning".to_string() } }); // or just using the `new_state` constructor Val::new_state(|state: MyState| state.counter + 1); }
State independent values
State independent means, you do not need to access the global application State
to produce a value.
This means that you can use literals or other "constants" or simply state independent values.
You can create these values using the Val::new_val
, the val!()
macro or simply cast a value into a Val
like this:
#![allow(unused)] fn main() { // constructor Val::new_val(3); // `val!()` macro val!("Hello World".to_string()); // cast `into()` the `Val` 103.into(); }
State Mutability
When using Val
to access data, a State
is always borrowed as immutable variable. This means you only have read-access to the inner value.
If you want to make a widget with mutable state (like an on_click
handler), you can use a custom Fn(&mut State)
and call it in your update
function, when creating a widget.