Editing an Item from a Form in React
As I was practicing the add, update, and delete functionality for a react app, I found the updating section challenging. I wanted to write a blog about it, to help with solidifying the approach. There are many different ways to approach updating an object in a list, but I found this approach pretty straightforward.
Let's start by creating a form. This form will be used to add and update an item in a list of items.
const TaskForm =({onSubmit, btnText})=>{
const [name, setName] = useState('')
const [complete, setComplete] = useState('')
const handleTextChange =(e)=>{
setName(e.target.value)
}
const handleSubmit=(e)=>{
e.preventDefault()
onSubmit({
name: name,
isComplete: complete === 'complete'
})
setName('')
setComplete('')
}
return (
<form onSubmit={handleSubmit}>
<label>
Task:
<input
type='text'
name='name'
value={name}
onChange={handleTextChange} />
</label>
<label>
<input
type="radio"
name="complete"
value="complete"
checked={complete ==='complete'}
onChange={()=>setComplete('complete')}
/>
Complete
</label>
<label>
<input
type="radio"
name="incomplete"
value="incomplete"
checked={complete === 'incomplete'}
onChange={()=>setComplete('incomplete')}
/>
Incomplete
</label>
<button type='submit'>{btnText}</button>
</form>
)
}
The form looks like this:
This form is currently set to just add a task but we want to focus on using the same form to edit a task. Let's dive into that.
Using the same TaskForm component, we are going to pass down a few more props to dynamically change the TaskForm from adding a task to editing a task.
So one way to do this is by using a useEffect.
//In TaskForm.js
//pass the isEdit and editTask as props
const TaskForm =({onSubmit, btnText, editTask})=>{
const [name, setName] = useState('')
const [complete, setComplete] = useState('')
//add a useEffect
useEffect(()=>{
//in this condition we are making sure that editTask
//has has an object before trying to the set the name and complete
//state
if(editTask){
setName(editTask.name)
setComplete(editTask.isComplete ? 'complete': 'incomplete')
}
}, [isEdit, editTask])
const handleTextChange =(e)=>{
setName(e.target.value)
}
const handleSubmit=(e)=>{
e.preventDefault()
onSubmit({
name: name,
isComplete: complete === 'complete'
})
setName('')
setComplete('')
}
return (
<form onSubmit={handleSubmit}>
<label>
Task:
<input
type='text'
name='name'
value={name}
onChange={handleTextChange} />
</label>
<label>
<input
type="radio"
name="complete"
value="complete"
checked={complete ==='complete'}
onChange={()=>setComplete('complete')}
/>
Complete
</label>
<label>
<input
type="radio"
name="incomplete"
value="incomplete"
checked={complete === 'incomplete'}
onChange={()=>setComplete('incomplete')}
/>
Incomplete
</label>
<button type='submit'>{btnText}</button>
</form>
)
}
We are setting theeditTask
state in the parent component.editTask
is a state set to null
on initial render of the parent component, when the user clicks the edit button on one of the tasks, editTask
will be set to an object with the name
and isComplete
properties. Feel free to name these whatever name you want, the idea is to pass down the task that the user wants to edit. When the user clicks on a task to edit, that task will be populated in the form so the user can make changes to the task. You can then proceed to update the task in the list of tasks in the parent component using the map method.