Tauri Events: Real-Time Bidirectional Communication | Rust + React Tutorial (Lesson 34)
Video: Tauri Events: Real-Time Bidirectional Communication | Rust + React Tutorial (Lesson 34) by Taught by Celeste AI - AI Coding Coach
Watch full page →Tauri Events: Real-Time Bidirectional Communication | Rust + React Tutorial (Lesson 34)
Discover how to implement real-time, bidirectional communication between your Rust backend and React frontend using Tauri events. This tutorial explains the difference between commands and events, shows how to emit events from Rust, and how to listen to them in React with custom hooks to build dynamic UIs like progress bars and toast notifications.
Code
/// Rust: Emitting events from the backend using Tauri
use serde::Serialize;
use tauri::{AppHandle, Manager, Wry, Window};
use tauri::async_runtime::spawn;
use tauri::api::event::Emitter;
#[derive(Serialize)]
struct ProgressPayload {
progress: u8,
message: String,
}
#[tauri::command]
fn start_long_task(app: AppHandle) {
// Spawn a thread to simulate a long-running task emitting progress events
spawn(async move {
for i in 0..=100 {
let payload = ProgressPayload {
progress: i,
message: format!("Progress: {}%", i),
};
// Emit event "progress-update" to all windows
app.emit_all("progress-update", payload).unwrap();
// Simulate work
std::thread::sleep(std::time::Duration::from_millis(50));
}
// Emit completion event
app.emit_all("task-complete", "Download finished!").unwrap();
});
}
// React + TypeScript: Listening to Tauri events with hooks
import { useEffect, useState } from "react";
import { listen, UnlistenFn } from "@tauri-apps/api/event";
interface ProgressPayload {
progress: number;
message: string;
}
export function useProgress() {
const [progress, setProgress] = useState(0);
const [message, setMessage] = useState("");
useEffect(() => {
// Listen for progress updates
let unlistenProgress: UnlistenFn;
let unlistenComplete: UnlistenFn;
async function setupListeners() {
unlistenProgress = await listen("progress-update", event => {
setProgress(event.payload.progress);
setMessage(event.payload.message);
});
unlistenComplete = await listen("task-complete", event => {
setMessage(event.payload);
// Optionally trigger a toast notification here
});
}
setupListeners();
// Cleanup listeners on unmount
return () => {
unlistenProgress && unlistenProgress();
unlistenComplete && unlistenComplete();
};
}, []);
return { progress, message };
}
Key Points
- Commands in Tauri follow a request-response pattern, while events enable the backend to push updates proactively to the frontend.
- Use
app.emit_all(eventName, payload)in Rust to emit events with typed payloads serialized to JSON. - In React, listen to Tauri events with the
listenAPI insideuseEffect, ensuring to unregister listeners on cleanup. - Typed event payloads in TypeScript provide type safety and improve developer experience with autocomplete.
- Combining Tauri events with UI libraries like shadcn/ui allows building responsive components like progress bars and toast notifications that update in real time.