Editing Tasks
In this tutorial, we’ll add the ability for users to edit their tasks by tapping on them. This will open a dialog where they can modify the task’s title and category.
Step 1: Update the Task Component
Section titled “Step 1: Update the Task Component”Now we’ll modify our Task component to include the dialog functionality.
First, add the imports needed to the top of the components/Task.tsx component:
import React from 'react';import { TouchableOpacity, View } from "react-native";
import { Text } from '@/components/ui/text';import { Checkbox } from '@/components/ui/checkbox';import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogTrigger, DialogDescription,} from "@/components/ui/dialog";import { Button } from "@/components/ui/button";import { Input } from "@/components/ui/input";
import { ITask } from '@/app';
interface TaskProps { task: ITask;}
// Other code here...Step 2: Implement the Dialog UI
Section titled “Step 2: Implement the Dialog UI”Replace the Task component function with the code below.
What’s Happening Here?
Section titled “What’s Happening Here?”- We’ve wrapped our task in a
Dialogcomponent - The
DialogTriggeropens the dialog when the user taps on a task - Inside
DialogContent, we’ve created:- A header with title and description
- Input fields pre-filled with the current task details
- Footer buttons to save or cancel changes
Testing Your Changes
Section titled “Testing Your Changes”After implementing these changes:
-
Start your server with
npm run dev(if you need to) -
Tap on any task in your app
-
A dialog will appear with the current title and category
-
Click “Cancel” or “Save changes” to close the dialog
import React from 'react';import { View } from 'react-native';
import { Button } from '@/components/ui/button';import { DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose,} from '@/components/ui/dialog';import { Input } from '@/components/ui/input';import { Text } from '@/components/ui/text';
import { ITask } from '@/app';
interface TaskDialogProps { task: ITask; setTask: (task: ITask) => void; setShowDialog: (showDialog: boolean) => void; showDialog: boolean;}function TaskDialogue({ task, setTask, setShowDialog, showDialog }: TaskDialogProps) { return ( <DialogContent className="max-w-5/6"> <DialogHeader> <DialogTitle>Edit Task</DialogTitle> <DialogDescription>Make changes to your task details here.</DialogDescription> </DialogHeader>
<View className="gap-4"> <Input defaultValue={task.title} placeholder="Task title" /> <Input defaultValue={task.category} placeholder="Category" /> </View>
<DialogFooter className="mt-4 flex flex-row gap-2"> <DialogClose className="border-brand-primary w-1/2 border" asChild> <Button variant="outline" className="border-brand-primary rounded-3xl border"> <Text className="text-brand-primary">Cancel</Text> </Button> </DialogClose> <DialogClose asChild> <Button className="bg-brand-primary w-1/2 rounded-3xl"> <Text className="text-background">Save changes</Text> </Button> </DialogClose> </DialogFooter> </DialogContent> );}
export { TaskDialogue };Step 4: Add event handlers to the dialogue
Section titled “Step 4: Add event handlers to the dialogue”We need to add event handlers to the dialogue to update the task when the user saves their changes.
Notice that:
- We are now wrapping the whole dialogue in a
Dialogcomponent. This is because we will be controlling the open/closed state of the dialog from the parentTaskcomponent later. - We are setting
editedTitleandeditedCategoryas state variables to have full control of the user’s changes. - We are using the
setTaskprop to update the task from its parent. This is a function that will be passed down from theTaskcomponent.
16 collapsed lines
import React from 'react';import { View } from 'react-native';
import { Button } from '@/components/ui/button';import { DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose,} from '@/components/ui/dialog';import { Input } from '@/components/ui/input';import { Text } from '@/components/ui/text';
import { ITask } from '@/app';
interface TaskDialogProps { task: ITask; setTask: (task: ITask) => void; setShowDialog: (showDialog: boolean) => void; showDialog: boolean;}function TaskDialogue({ task, setTask, setShowDialog, showDialog }: TaskDialogProps) { const [editedTitle, setEditedTitle] = React.useState(task.title); const [editedCategory, setEditedCategory] = React.useState(task.category);
const handleUpdateTitle = (title: string) => { setEditedTitle(title); }; const handleUpdateCategory = (category: string) => { setEditedCategory(category); };
const handleSave = () => { const nextTask = { ...task, title: editedTitle, category: editedCategory, };
setTask(nextTask); setShowDialog(false); };
return ( <DialogContent className="max-w-5/6">5 collapsed lines
<DialogHeader> <DialogTitle>Edit Task</DialogTitle> <DialogDescription>Make changes to your task details here.</DialogDescription> </DialogHeader>
<View className="gap-4"> <Input defaultValue={task.title} placeholder="Task title" onChangeText={handleUpdateTitle} /> <Input defaultValue={task.category} placeholder="Category" onChangeText={handleUpdateCategory} /> </View>
<DialogFooter className="mt-4 flex flex-row gap-2"> <DialogClose className="border-brand-primary w-1/2 border" asChild>5 collapsed lines
<Button variant="outline" className="border-brand-primary rounded-3xl border"> <Text className="text-brand-primary">Cancel</Text> </Button> </DialogClose> <DialogClose asChild> <Button className="bg-brand-primary w-1/2 rounded-3xl" onPress={handleSave} > <Text className="text-background">Save changes</Text> </Button> </DialogClose> </DialogFooter> </DialogContent> );}Step 5: Use TaskDialogue in Task
Section titled “Step 5: Use TaskDialogue in Task”Finally, let’s update our Task component to use the new TaskDialogue:
import * as React from "react";import { TouchableOpacity, View } from "react-native";
import { TaskDialogue } from "@/components/TaskDialogue";import { Text } from '@/components/ui/text';import { Checkbox } from '@/components/ui/checkbox';import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogTrigger, DialogDescription,} from '@/components/ui/dialog';import { Button } from '@/components/ui/button';import { Input } from '@/components/ui/input';9 collapsed lines
import { ITask } from '@/app';
interface TaskProps { task: ITask;}
function Task({ task: initialTask }) { const [task, setTask] = React.useState(initialTask); const [showDialog, setShowDialog] = React.useState(false);
const handleSetChecked = () => { const nextChecked = !task.isChecked; setTask({ ...task, isChecked: nextChecked }); };
return (15 collapsed lines
<Dialog> <DialogTrigger asChild> <TouchableOpacity className="flex w-full flex-row" delayLongPress={500}> <View className="flex h-full w-24 px-8 py-5"> <Checkbox className="border-foreground checked:bg-foreground" checked={checked} onCheckedChange={setChecked} /> </View> <View className="border-foreground-transparent flex h-full flex-1 gap-1 border-b py-4"> <Text className="text-foreground text-xl">{title}</Text> <Text className="text-foreground-transparent text-xl">{category}</Text> </View> </TouchableOpacity> </DialogTrigger>
<DialogContent className="max-w-5/6"> <DialogHeader> <DialogTitle>Edit Task</DialogTitle> <DialogDescription>Make changes to your task details here.</DialogDescription> </DialogHeader>
<View className="gap-4"> <Input defaultValue={title} placeholder="Task title" /> <Input defaultValue={category} placeholder="Category" /> </View>
<DialogFooter className="mt-4 flex flex-row gap-2"> <DialogClose className="border-brand-primary w-1/2 border" asChild> <Button variant="outline" className="border-brand-primary rounded-3xl border"> <Text className="text-brand-primary">Cancel</Text> </Button> </DialogClose> <DialogClose asChild> <Button className="bg-brand-primary w-1/2 rounded-3xl"> <Text className="text-background">Save changes</Text> </Button> </DialogClose> </DialogFooter> </DialogContent> <TaskDialogue task={task} setTask={setTask} setShowDialog={setShowDialog} showDialog={showDialog} /> </Dialog> );}
export { Task };What’s Happening Here?
Section titled “What’s Happening Here?”- Code Organization: We’ve moved the Task component to its own file and created a separate TaskDialog component for better code organization.
- Task Component:
- Now accepts a complete
taskobject instead of individual props - Manages its own state with
useState - Opens the dialog on long press with
onLongPress - Handles checkbox state changes with
handleSetChecked
- Now accepts a complete
- TaskDialog Component:
- Manages the edited title and category with separate state variables
- Provides handlers for updating the title and category
- Implements a
handleSavefunction that updates the task with the edited values - Closes the dialog after saving
- HomeScreen Component:
- Simplified to just render the Task components with the task data
Testing Your Changes
Section titled “Testing Your Changes”After implementing these changes:
- Tap on the task in your app
- A dialog will appear with the current title and category
- You can modify these values
- Click “Cancel” to close without saving or “Save changes” to close the dialog
- The task will update to display its new values
This implementation provides a complete task editing experience with proper state management and component organization.
Next Steps
Section titled “Next Steps”In the next tutorial, we will look at how to add a new task to the list.