Membuat Aplikasi Desktop To-Do List dengan Tauri dan React: Alternatif Ringan untuk Developer Indonesia
Pelajari cara membuat aplikasi desktop to-do list menggunakan Tauri dan React. Tutorial ini cocok untuk developer Indonesia yang ingin beralih dari Electron ke solusi yang lebih ringan dan cepat.
Kenapa Tauri? Alternatif Electron yang Lebih Enteng
Kamu mungkin sudah sering dengar tentang Electron—framework untuk bikin aplikasi desktop pakai teknologi web. Tapi, tahukah kamu kalau aplikasi Electron cenderung boros RAM dan ukuran file-nya besar? Nah, di sinilah Tauri hadir sebagai alternatif. Tauri menggunakan backend Rust yang membuat aplikasi lebih ringan (bisa seukuran 2-5 MB) dan konsumsi memori lebih rendah. Cocok banget untuk kamu yang mau bikin aplikasi desktop sederhana tanpa bikin laptop lemot.
Dalam tutorial ini, kita akan membuat aplikasi to-do list sederhana. Kamu akan belajar cara setup proyek Tauri dengan React, komunikasi antara frontend dan backend, serta build aplikasi untuk Windows, macOS, atau Linux.
Prasyarat
Sebelum mulai, pastikan kamu sudah install:
- Node.js (versi 16 atau lebih baru)
- Rust (versi 1.60 atau lebih baru)
- Cargo (biasanya sudah termasuk saat install Rust)
- Git (opsional)
Kalau belum punya Rust, kunjungi rustup.rs dan ikuti petunjuk instalasi. Untuk Node.js, download dari nodejs.org.
Langkah 1: Inisialisasi Proyek Tauri + React
Buka terminal dan jalankan perintah berikut:
npm create tauri-app@latest
Ikuti wizard:
- Project name:
todo-tauri - Choose your package manager:
npm - Choose UI template:
React - Choose your React flavor:
TypeScript(biar lebih rapi)
Setelah selesai, masuk ke folder proyek:
cd todo-tauri
Install dependensi:
npm install
Coba jalankan aplikasi untuk melihat template default:
npm run tauri dev
Jika berhasil, akan muncul jendela aplikasi dengan halaman React standar. Tutup jendela untuk melanjutkan.
Langkah 2: Struktur Folder Proyek
Struktur folder-nya seperti ini:
todo-tauri/
├── src/ # Kode React
├── src-tauri/ # Kode Rust (backend)
├── public/
├── package.json
└── ...
Kita akan fokus di folder src/ untuk frontend dan src-tauri/src/ untuk backend.
Langkah 3: Membuat Komponen To-Do List
Buka file src/App.tsx dan ganti dengan kode berikut:
import { useState, useEffect } from 'react';
import { invoke } from '@tauri-apps/api/tauri';
import './App.css';
interface Todo {
id: number;
text: string;
completed: boolean;
}
function App() {
const [todos, setTodos] = useState<Todo[]>([]);
const [input, setInput] = useState('');
useEffect(() => {
// Load todos from backend saat aplikasi dimulai
invoke<Todo[]>('get_todos').then(setTodos);
}, []);
const addTodo = async () => {
if (!input.trim()) return;
const newTodo = await invoke<Todo>('add_todo', { text: input });
setTodos([...todos, newTodo]);
setInput('');
};
const toggleTodo = async (id: number) => {
const updated = await invoke<Todo>('toggle_todo', { id });
setTodos(todos.map(t => t.id === id ? updated : t));
};
const deleteTodo = async (id: number) => {
await invoke('delete_todo', { id });
setTodos(todos.filter(t => t.id !== id));
};
return (
<div className="container">
<h1>To-Do List</h1>
<div className="input-row">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && addTodo()}
placeholder="Tambah tugas baru..."
/>
<button onClick={addTodo}>Tambah</button>
</div>
<ul>
{todos.map(todo => (
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>Hapus</button>
</li>
))}
</ul>
</div>
);
}
export default App;
Langkah 4: Styling Sederhana
Buka file src/App.css dan ganti dengan:
.container {
max-width: 500px;
margin: 50px auto;
font-family: sans-serif;
}
.input-row {
display: flex;
gap: 8px;
margin-bottom: 20px;
}
.input-row input {
flex: 1;
padding: 8px;
font-size: 16px;
}
.input-row button {
padding: 8px 16px;
background: #4caf50;
color: white;
border: none;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
align-items: center;
gap: 8px;
padding: 8px;
border-bottom: 1px solid #ccc;
}
li.completed span {
text-decoration: line-through;
color: #999;
}
li button {
margin-left: auto;
background: #f44336;
color: white;
border: none;
padding: 4px 8px;
cursor: pointer;
}
Langkah 5: Membuat Backend Rust untuk Menyimpan Data
Sekarang kita akan membuat perintah Rust yang bisa dipanggil dari frontend. Buka file src-tauri/src/main.rs dan ganti isinya:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::sync::Mutex;
use tauri::State;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct Todo {
id: u32,
text: String,
completed: bool,
}
struct TodoState {
todos: Mutex<Vec<Todo>>,
next_id: Mutex<u32>,
}
#[tauri::command]
fn get_todos(state: State<TodoState>) -> Vec<Todo> {
state.todos.lock().unwrap().clone()
}
#[tauri::command]
fn add_todo(state: State<TodoState>, text: String) -> Todo {
let mut todos = state.todos.lock().unwrap();
let mut id = state.next_id.lock().unwrap();
let todo = Todo {
id: *id,
text,
completed: false,
};
*id += 1;
todos.push(todo.clone());
todo
}
#[tauri::command]
fn toggle_todo(state: State<TodoState>, id: u32) -> Result<Todo, String> {
let mut todos = state.todos.lock().unwrap();
if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {
todo.completed = !todo.completed;
Ok(todo.clone())
} else {
Err("Todo not found".to_string())
}
}
#[tauri::command]
fn delete_todo(state: State<TodoState>, id: u32) -> Result<(), String> {
let mut todos = state.todos.lock().unwrap();
let len = todos.len();
todos.retain(|t| t.id != id);
if todos.len() < len {
Ok(())
} else {
Err("Todo not found".to_string())
}
}
fn main() {
tauri::Builder::default()
.manage(TodoState {
todos: Mutex::new(vec![]),
next_id: Mutex::new(1),
})
.invoke_handler(tauri::generate_handler![
get_todos,
add_todo,
toggle_todo,
delete_todo
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Penjelasan:
TodoStatemenyimpan daftar todos dan ID counter.Mutexdipakai karena state diakses dari banyak thread.#[tauri::command]membuat fungsi bisa dipanggil dari frontend denganinvoke.- Di
main, kita daftarkan state dan handler commands.
Langkah 6: Jalankan Aplikasi
Kembali ke terminal, jalankan:
npm run tauri dev
Sekarang kamu bisa menambah, menandai selesai, dan menghapus tugas. Setiap perubahan hanya tersimpan di memori selama aplikasi berjalan. Kalau mau penyimpanan permanen, kamu bisa integrasikan dengan file atau database SQLite di Rust.
Langkah 7: Build Aplikasi
Setelah selesai, kamu bisa build aplikasi menjadi installer untuk sistem operasi kamu:
npm run tauri build
Hasil build ada di src-tauri/target/release/bundle/. Kamu bisa bagikan installer itu ke teman atau upload ke website.
Kesimpulan
Selamat! Kamu berhasil membuat aplikasi desktop to-do list dengan Tauri dan React. Perbandingan ukuran file: aplikasi Electron minimal 150 MB, sedangkan Tauri hanya sekitar 5 MB. Performa juga lebih responsif. Dengan Tauri, kamu bisa bikin aplikasi desktop yang powerfull tanpa mengorbankan resource.
Sebagai latihan lanjutan, coba tambahkan fitur:
- Penyimpanan SQLite agar data tidak hilang saat aplikasi ditutup.
- Drag and drop untuk mengurutkan tugas.
- Notifikasi menggunakan sistem tray.
Sumber daya:
Semoga tutorial ini bermanfaat buat kamu yang ingin eksplorasi pengembangan aplikasi desktop modern. Selamat coding!