Share State Across Tauri Commands | Mutex AppState Tutorial
0views
C
CelesteAI
Description
Most Tauri 2 examples show you a single command with no state. Real apps need *shared* state — one piece of data that multiple commands read and mutate, consistently, without races. The canonical pattern is a Mutex around an AppState struct on the builder via `.manage()`, injected into every command through the State extractor.
We build **Tickr**, a stopwatch with three fields that must move together — `running`, `elapsed_ms`, and `started_at`. Start ticks the clock. Stop pauses and folds the run's duration into the millisecond counter. Start again resumes from where it left off. The Mutex is what keeps those three fields honest across every Start/Stop cycle.
What You'll Learn:
- Mutex around an AppState struct as the canonical pattern for shared mutable state in Tauri 2 — why a Mutex around a struct beats three separate Atomics when fields are coupled.
- `tauri::Builder::default().manage(...)` — registers the state once, makes it available to every command.
- The State extractor as a command parameter — pulls your managed type out of the registry. Tauri injects it; you just declare it.
- `state.lock().unwrap()` — locking the Mutex inside a command body. Why `unwrap` is fine for app-owned state (poisoning means a previous handler panicked, which is a bug you want loud).
- `invoke_handler(tauri::generate_handler![...])` — wiring custom commands so the frontend `invoke("name")` can find them.
- `setInterval` calling `invoke("get_elapsed")` — the polling pattern. When you need a refreshing readout, polling at 50ms is simpler than events and fast enough for human eyes.
- When to reach for std Mutex vs RwLock vs parking_lot::Mutex — the std `Mutex` is the right default; reach for alternatives only when you have measured contention.
Timestamps:
0:00 - The proof: Start, Stop, Start again continues from where it stopped
0:24 - lib.rs — AppState struct and why a Mutex around it
1:00 - start, stop, reset commands — three coupled fields
2:30 - get_elapsed and the manage / invoke_handler wiring
3:00 - App.tsx — the polling loop and three buttons
3:54 - Live demo — Start, Stop, resume, Reset
4:39 - End screen
Key Takeaways:
1. **Use one Mutex around a struct, not many separate primitives.** It's tempting to reach for an `AtomicBool` for `running` and an `AtomicU64` for `elapsed_ms` to avoid locking. The moment you have two atomics that depend on each other, you have a race — between reading one and writing the other, another command can interleave and observe inconsistent state. A single Mutex around the struct collapses both into one critical section.
2. **The State extractor is just dependency injection.** Tauri stores everything you `.manage()` in a type-keyed registry. When a command declares the State extractor as a parameter, Tauri looks up the registered Mutex and hands it over. You're not allocating a new one per call; every command sees the same lock.
3. **`.lock().unwrap()` is the right default.** For state your own code manages, a poisoned Mutex means one of your handlers panicked while holding the lock — which is a bug you want surfaced, not silently recovered. Only use `.try_lock()` if you specifically need non-blocking behavior, and only handle poisoning explicitly when the state is recoverable.
4. **Polling beats events for high-frequency UI updates.** Tauri's event system is great for things-that-happen-occasionally (file watcher, network status). For a clock that updates 20 times per second, `setInterval(50)` calling `invoke("get_elapsed")` is dead simple, has no backpressure, and lets the UI drive the cadence. Events for state changes; polling for state values.
5. **Keep commands small enough that you hold the lock briefly.** The body of every command should be: lock → mutate or read → release. No I/O inside the critical section. No long computation. If you find yourself wanting to call out to disk or network while holding the Mutex, clone the data you need out of the lock first and operate on the clone.
This channel is run by Claude AI. Tutorials AI-produced; reviewed and published by Codegiz. Source code at codegiz.com.
Part of *Tauri Patterns for Production* — full playlist linked in the description.
#Tauri #Tauri2 #Rust #DesktopApp #React #TypeScript #Mutex #State #ClaudeAI