How to Create a Todo App in Svelte: Simple Step-by-Step Guide
To create a todo app in
Svelte, define a reactive array to hold tasks, use bind:value on an input to capture new todos, and update the list with event handlers. Render the todo list with {#each} blocks and update state reactively to reflect changes instantly.Syntax
A basic todo app in Svelte uses these parts:
- Reactive variables: Use
letto declare state that updates the UI automatically. - Event handlers: Use
on:clickoron:submitto respond to user actions. - Two-way binding: Use
bind:valueon inputs to keep variables in sync with user input. - List rendering: Use
{#each}blocks to display arrays dynamically.
svelte
<script> let todos = []; let newTodo = ''; function addTodo() { if (newTodo.trim() !== '') { todos = [...todos, newTodo.trim()]; newTodo = ''; } } </script> <input bind:value={newTodo} placeholder="Add new todo" /> <button on:click={addTodo}>Add</button> <ul> {#each todos as todo} <li>{todo}</li> {/each} </ul>
Output
An input box with placeholder 'Add new todo', an 'Add' button, and a list below that shows added todo items.
Example
This example shows a complete todo app where you can add tasks and see them listed instantly. It uses reactive variables, event handling, and list rendering.
svelte
<script> let todos = []; let newTodo = ''; function addTodo() { if (newTodo.trim() !== '') { todos = [...todos, newTodo.trim()]; newTodo = ''; } } function removeTodo(index) { todos = todos.filter((_, i) => i !== index); } </script> <h1>Todo App</h1> <input bind:value={newTodo} placeholder="Add new todo" on:keydown={(e) => e.key === 'Enter' && addTodo()} /> <button on:click={addTodo}>Add</button> <ul> {#each todos as todo, index} <li> {todo} <button aria-label="Remove todo" on:click={() => removeTodo(index)}>x</button> </li> {/each} </ul>
Output
A heading 'Todo App', an input box with placeholder, an 'Add' button, and a list of todos each with a remove 'x' button.
Common Pitfalls
Common mistakes when building a todo app in Svelte include:
- Not updating the array immutably, which can prevent UI updates.
- Forgetting to clear the input after adding a todo.
- Not handling empty or whitespace-only inputs.
- Using index as key in
{#each}without care, which can cause rendering issues if items reorder.
svelte
<!-- Wrong: mutating array directly --> <script> let todos = []; let newTodo = ''; function addTodo() { if (newTodo.trim() !== '') { todos.push(newTodo.trim()); // This won't update UI newTodo = ''; } } </script> <!-- Right: create new array --> <script> let todos = []; let newTodo = ''; function addTodo() { if (newTodo.trim() !== '') { todos = [...todos, newTodo.trim()]; // UI updates correctly newTodo = ''; } } </script>
Quick Reference
Summary tips for building a todo app in Svelte:
- Use
letfor reactive state variables. - Use
bind:valueon inputs for easy two-way data binding. - Use
{#each}to loop over todos and render them. - Update arrays immutably to trigger UI updates.
- Handle empty inputs and clear input after adding.
- Add accessible labels on buttons for better usability.
Key Takeaways
Use reactive variables with let to store todos and input values.
Bind input value with bind:value for easy user input handling.
Render todos with {#each} and update arrays immutably for UI refresh.
Clear input after adding a todo and prevent empty entries.
Add accessible labels and keyboard support for better usability.