new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Tauri · all subjects

state management

22 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

State management using Manager API

Tauri provides state management through the Manager API. You manage state in the setup function using app.manage() to store an application state struct, then access it later with app.state::<T>().

State management example with AppData struct

Example of basic state management: Create a struct AppData with welcome_message field, call app.manage(AppData { welcome_message: "Welcome to Tauri!" }) in the setup function, and access it later with app.state::<AppData>().

Use Mutex for mutable state

Wrap state in std::sync::Mutex to allow mutation across multiple threads and avoid data races. Lock the mutex with state.lock().unwrap() to get mutable access, and it automatically unlocks when the MutexGuard is dropped at the end of the scope.

Mutexed state example with counter

Example of mutable state: Define struct AppState { counter: u32 }, call app.manage(Mutex::new(AppState::default())) in setup, then access with app.state::<Mutex<AppState>>() and lock it with state.lock().unwrap() to modify.

Arc not needed for State wrapper

Do not wrap state in Arc when storing it in State because Tauri handles this internally. AppHandle instances are cheap to clone and can be moved into threads to access state via the Manager trait if State's lifetime requirements prevent direct state movement.

Access state outside commands with Manager trait

Access state in event handlers or other contexts using the Manager trait. Call window.app_handle() to get an AppHandle, then use app_handle.state::<T>() to retrieve state. This is useful when state cannot be injected as a command parameter.

Window event handler state access example

Example accessing state in a window event handler: Get app_handle from window with window.app_handle(), retrieve state with app_handle.state::<Mutex<AppState>>(), then lock and modify it.

Manager API for state management

Tauri provides a Manager API to manage application state and read state when commands are invoked. Any type implementing the Manager trait, such as an App instance, can access its managed state later.

Basic state management setup

State is registered in the setup function using app.manage(). For example: Builder::default().setup(|app| { app.manage(AppData { welcome_message: "Welcome to Tauri!" }); Ok(()) }).run(tauri::generate_context!()).unwrap();

Accessing state from Manager trait

State can be accessed using app.state::<StateType>() on any type implementing the Manager trait.

Interior mutability for shared mutable state

Rust prevents direct mutation of values shared between threads or controlled through shared pointers like Arc. Interior mutability patterns, such as Mutex, must be used to wrap state and manage concurrent access.

Wrapping state with Mutex

Use std::sync::Mutex to wrap mutable state for thread-safe access. Lock the mutex with .lock().unwrap() to get mutable access, and the mutex automatically unlocks when the MutexGuard is dropped.

Standard library Mutex vs async Mutex

Standard library Mutex is often preferred in async code and is safe to use, contrary to common belief. Async Mutex (like Tokio's) is primarily useful for shared mutable access to IO resources like database connections or when MutexGuard must be held across await points.

Arc not needed for State types

Arc is not required for types stored in Tauri's State because Tauri handles the reference counting internally. If State's lifetime requirements prevent moving to a new thread, move AppHandle instead, which is cheap to clone.

Accessing state in commands

State can be accessed in command functions by injecting it as a parameter: #[tauri::command] fn increase_counter(state: State<'_, Mutex<AppState>>) -> u32 { let mut state = state.lock().unwrap(); state.counter += 1; state.counter }

Async command state access with Tokio Mutex

For async commands using Tokio's async Mutex, state is accessed similarly: #[tauri::command] async fn increase_counter(state: State<'_, Mutex<AppState>>) -> Result<u32, ()> { let mut state = state.lock().await; state.counter += 1; Ok(state.counter) } Note: async commands must return Result type.

Accessing state outside commands

State can be accessed outside command context using the Manager trait's state() method on types like AppHandle. For example, in event handlers: let app_handle = window.app_handle(); let state = app_handle.state::<Mutex<AppState>>();

Manager trait state access in event handlers

State can be accessed in event handlers like on_window_event by obtaining the app handle from the window and calling state() method on it.

State type mismatch causes runtime panic

Using the wrong type in the State parameter causes a runtime panic, not a compile-time error. For example, using State<'_, AppState> instead of State<'_, Mutex<AppState>> results in no managed state existing for that type.

Type alias for state wrapper

To prevent state type mismatch errors, wrap state in a type alias: type AppState = Mutex<AppStateInner>; However, use the type alias directly without re-wrapping it in Mutex.

AppHandle cloning for thread state access

When State's lifetime requirements prevent moving to a new thread, move AppHandle to that thread instead. AppHandle is deliberately designed to be cheap to clone and allows retrieving state from outside command context.

Managed state access in commands

Tauri can manage state using tauri::Builder::manage(). State can be accessed in commands using tauri::State<T> as a parameter, which provides access to the managed state object.

Give your agent this brain