Step 6: Add Success Feedback
Time: ~5 minutes | Type: UX | Concepts: User feedback, toast integration
What We're Building
Adding success toast notifications to all CRUD operations:
- "Todo created!" after creating
- "Changes saved!" after updating
- "Todo deleted!" after deleting
The Prompt for AI
💡 Ask AI to help you add success toasts:
I have a useToast hook that provides showToast(message, type). I need to add success toasts to: 1. CreateTodoPage - after successful creation 2. EditTodoPage - after successful update 3. Delete function - after successful deletion For each operation: - Show appropriate success message - Use 'success' type - Toast should appear before redirect Can you show me where and how to add showToast() calls?
Wait for AI's response, then apply the changes.
Part 1: Add Success Toast to Create
Find your CreateTodoPage component:
Before (no success feedback):
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
try {
await addDoc(collection(db, 'todos'), {
title,
completed: false,
userId: currentUser.uid,
createdAt: Timestamp.now()
});
router.push('/todos'); // Just redirects
} catch (error) {
console.error('Failed to create todo:', error);
} finally {
setLoading(false);
}
}After (with success toast):
import { useToast } from '../hooks/useToast';
function CreateTodoPage() {
const { showToast } = useToast(); // Add this
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
try {
await addDoc(collection(db, 'todos'), {
title,
completed: false,
userId: currentUser.uid,
createdAt: Timestamp.now()
});
showToast('Todo created!', 'success'); // SUCCESS: Show success toast
router.push('/todos');
} catch (error) {
console.error('Failed to create todo:', error);
showToast('Could not create todo. Please try again.', 'error'); // Error toast
} finally {
setLoading(false);
}
}
// ... rest of component
}Key changes:
- Import and call
useToast() - Show success toast after successful creation
- Show error toast on failure
Part 2: Add Success Toast to Update
Find your EditTodoPage component:
import { useToast } from '../hooks/useToast';
function EditTodoPage() {
const { showToast } = useToast();
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
try {
await updateDoc(doc(db, 'todos', todoId), {
title,
completed
});
showToast('Changes saved!', 'success'); // SUCCESS: Show success toast
router.push('/todos');
} catch (error) {
console.error('Failed to update todo:', error);
showToast('Could not save changes. Please try again.', 'error');
} finally {
setLoading(false);
}
}
// ... rest of component
}Part 3: Add Success Toast to Delete
Find your delete function (likely in TodosPage or TodoItem component):
Before (no success feedback):
async function handleDelete(todoId: string) {
if (confirm('Delete this todo?')) {
await deleteDoc(doc(db, 'todos', todoId));
// Refresh list
}
}After (with success toast):
import { useToast } from '../hooks/useToast';
function TodosPage() {
const { showToast } = useToast();
async function handleDelete(todoId: string) {
if (confirm('Delete this todo?')) {
try {
await deleteDoc(doc(db, 'todos', todoId));
showToast('Todo deleted!', 'success'); // SUCCESS: Show success toast
// Refresh list (re-fetch or filter state)
} catch (error) {
console.error('Failed to delete todo:', error);
showToast('Could not delete todo. Please try again.', 'error');
}
}
}
// ... rest of component
}Part 4: Update Toggle Complete (Optional)
If you have a "mark complete" checkbox:
async function handleToggleComplete(todoId: string, currentStatus: boolean) {
try {
await updateDoc(doc(db, 'todos', todoId), {
completed: !currentStatus
});
// Optional: Show toast for this too
showToast(
!currentStatus ? 'Todo completed!' : 'Todo marked incomplete',
'success'
);
} catch (error) {
console.error('Failed to update status:', error);
showToast('Could not update status. Please try again.', 'error');
}
}Note: For checkboxes, toasts are optional (visual change is feedback enough).
Verification
Test all success toasts:
Test 1: Create Success
- Go to
/todos/new - Fill form: title "Test toast"
- Click "Create Todo"
- Expected:
- [ ] Loading state shows
- [ ] Green toast appears: "Todo created!"
- [ ] Redirects to list
- [ ] New todo appears in list
- [ ] Toast auto-dismisses after 3s
Test 2: Update Success
- Click "Edit" on a todo
- Change title to "Updated with toast"
- Click "Save Changes"
- Expected:
- [ ] Loading state shows
- [ ] Green toast: "Changes saved!"
- [ ] Redirects to list
- [ ] Updated title appears
- [ ] Toast auto-dismisses
Test 3: Delete Success
- Click "Delete" on a todo
- Confirm deletion
- Expected:
- [ ] Green toast: "Todo deleted!"
- [ ] Todo disappears from list
- [ ] Toast auto-dismisses
Test 4: Error Handling
- Turn off internet/Wi-Fi
- Try to create a todo
- Expected:
- [ ] Red toast appears
- [ ] Message: "Could not create todo. Please try again."
- [ ] Stays on form (doesn't redirect)
- [ ] Input data preserved
- [ ] Toast auto-dismisses after 5s
Common Issues
Toast Not Appearing
Problem: useToast not called or ToastProvider missing.
Fix:
- Check
const { showToast } = useToast();at top of component - Verify ToastProvider wraps your app
- Check browser console for errors
Toast Shows But Wrong Message
Problem: Copy-paste error.
Fix: Check the message in showToast():
showToast('Todo created!', 'success'); // SUCCESS: Correct
showToast('Changes saved!', 'success'); // SUCCESS: For update
showToast('Todo deleted!', 'success'); // SUCCESS: For deleteToast Shows After Redirect
Problem: Toast appears then immediately disappears.
Fix: Toast shows in current page context. If you redirect immediately, it might not be visible long enough. This is usually fine, but if you want delay:
showToast('Todo created!', 'success');
await new Promise(resolve => setTimeout(resolve, 500)); // Wait 500ms
router.push('/todos');Note: Usually not necessary. The toast will appear briefly before redirect.
Multiple Toasts on Error
Problem: Toast shows multiple times.
Fix: Make sure try/catch doesn't nest. Only one showToast per error:
try {
await operation();
showToast('Success!', 'success');
} catch (error) {
showToast('Error message', 'error'); // Only show once
}Understanding Check
Before moving on, make sure you understand:
💡 Ask yourself:
- When should I show success toasts? (After every successful CRUD operation)
- What message for creating a todo? ("Todo created!")
- Should I show toast before or after redirect? (Before, so it's visible)
- What type for success toasts? ('success')
- Should I show toasts for checkbox toggles? (Optional, visual feedback is enough)
- What if the operation fails? (Show error toast with helpful message)
What You Learned
At this point you should have:
- ✅ Success toast after creating todo
- ✅ Success toast after updating todo
- ✅ Success toast after deleting todo
- ✅ Error toasts for all failures
- ✅ User always knows if action succeeded
- ✅ Professional feedback for all operations
- ✅ Better error handling with user-friendly messages
Next Step
Now that we have success feedback, let's improve error messages to be more user-friendly: