Gestion de Estado
Gestion de Estado
Los comandos en Tauri son funciones puras por defecto. Para compartir datos entre comandos, necesitas estado gestionado.
Estado basico
Definir y registrar
struct AppState {
counter: std::sync::Mutex<i32>,
api_url: String,
}
pub fn run() {
tauri::Builder::default()
.manage(AppState {
counter: std::sync::Mutex::new(0),
api_url: "https://api.ejemplo.com".into(),
})
.invoke_handler(tauri::generate_handler![increment, get_count, get_api_url])
.run(tauri::generate_context!())
.expect("error");
}
Acceder desde comandos
#[tauri::command]
fn increment(state: tauri::State<AppState>) -> i32 {
let mut counter = state.counter.lock().unwrap();
*counter += 1;
*counter
}
#[tauri::command]
fn get_count(state: tauri::State<AppState>) -> i32 {
*state.counter.lock().unwrap()
}
#[tauri::command]
fn get_api_url(state: tauri::State<AppState>) -> String {
state.api_url.clone()
}
tauri::State<T> inyecta automaticamente el estado registrado con .manage().
Mutex: por que y cuando
Rust no permite mutacion compartida sin sincronizacion. Si tu estado cambia:
Mutex<T>: acceso exclusivo, un thread a la vezRwLock<T>: multiples lectores o un escritor
use std::sync::Mutex;
struct Database {
items: Mutex<Vec<String>>,
}
#[tauri::command]
fn add_item(state: tauri::State<Database>, item: String) {
state.items.lock().unwrap().push(item);
}
#[tauri::command]
fn list_items(state: tauri::State<Database>) -> Vec<String> {
state.items.lock().unwrap().clone()
}
Si el estado es inmutable (configuracion, URLs), no necesitas Mutex:
struct Config {
version: String, // Solo lectura, sin Mutex
}
Multiples estados
Puedes registrar varios tipos de estado:
struct UserState {
name: Mutex<String>,
}
struct SettingsState {
theme: String,
}
pub fn run() {
tauri::Builder::default()
.manage(UserState { name: Mutex::new("Anonimo".into()) })
.manage(SettingsState { theme: "dark".into() })
.invoke_handler(tauri::generate_handler![get_user, get_theme])
.run(tauri::generate_context!())
.expect("error");
}
#[tauri::command]
fn get_user(state: tauri::State<UserState>) -> String {
state.name.lock().unwrap().clone()
}
#[tauri::command]
fn get_theme(state: tauri::State<SettingsState>) -> String {
state.theme.clone()
}
Estado con AppHandle
Si necesitas acceder al estado fuera de un comando (ej: en un listener o setup):
use tauri::Manager;
pub fn run() {
tauri::Builder::default()
.manage(AppState { counter: Mutex::new(0), api_url: "...".into() })
.setup(|app| {
let state = app.state::<AppState>();
println!("API: {}", state.api_url);
Ok(())
})
.run(tauri::generate_context!())
.expect("error");
}
Patron: estado con inicializacion asincrona
struct DbPool {
pool: sqlx::SqlitePool,
}
pub fn run() {
tauri::Builder::default()
.setup(|app| {
let pool = tauri::async_runtime::block_on(async {
sqlx::SqlitePool::connect("sqlite:app.db").await.unwrap()
});
app.manage(DbPool { pool });
Ok(())
})
.run(tauri::generate_context!())
.expect("error");
}
Resumen
.manage(T)registra estado accesible desde comandostauri::State<T>inyecta el estado automaticamente- Usa
Mutex<T>para estado mutable, nada para inmutable - Registra multiples tipos de estado con multiples
.manage() app.state::<T>()para acceder fuera de comandos- Usa
setup()para estado que necesita inicializacion asincrona
← Llamar al Frontend desde Rust | Indice | Siguiente: Sistema de Plugins →