React Part II
Let's take a moment to think what this component should do:
it should:
display the name and email of the contact
allow the user to press an "edit" button, which opens an edit form
in edit mode, when the user click "cancel", the edit form should close, and the content of it should reset
in edit mode, when the user click "ok", a request should be sent to update the user
if the user presses "delete", a request should be sent to delete the user
We can define two types of things here:
name
,email
are properties held in the parent component, and not decided by ourContact
component. They will be passed as propsupdateContact
,deleteContact
are methods in the parent component, and will be passed as props also.updateContact
anddeleteContact
both need to pass anid
property, which should be passed as a prop too.editMode
is an internal state of the component. The parent component isn't concerned if theContact
component is opened or closed.
We have state
, which means, we are going to use a class component.
Create a new file, Contact.js
Here's what we can write, based on what we know:
// front/src/Contact.js
import React from 'react'
export default class Contact extends React.Component{
state = {
editMode:false
}
toggleEditMode = () => {
const editMode = !this.state.editMode
this.setState({editMode})
}
renderEditMode(){
const { id, name, email, updateContact, deleteContact } = this.props
return (<div> edit mode</div>)
}
renderViewMode(){
const { id, name, email, updateContact, deleteContact } = this.props
return (<div>view mode</div>)
}
render(){
const { editMode } = this.state
if(editMode){
return this.renderEditMode()
}
else{
return this.renderViewMode()
}
}
}
We already have renderViewMode
. It's what we were using previously in the App
loop.
Let's copy paste it out of there, and modify it slightly:
...
renderViewMode(){
const { id, name, email, deleteContact } = this.props
return (
<div>
<span>
{id} - {name}
</span>
<button onClick={() => deleteContact(id)} className="warning">x</button>
</div>
)
}
...
We still have to handle renderEditMode
. Wait! It's suspiciously close to the "create" form! Let's copy-paste it from there. We need to operate a few changes though:
Remove references to
state
andsetState
, since in this context, the values don't come from the state anymore.Change
value
todefaultValue
. We want to set the starting value, but we do not want to track further state changesAdd a new
onSubmit
function that will useupdateContact
Add a
name
property to each input, so we can find them back
...
renderEditMode(){
const { name, email } = this.props
return(
<form className="third" onSubmit={this.onSubmit} onReset={this.toggleEditMode}>
<input
type="text"
placeholder="name"
name="contact_name_input"
defaultValue={name}
/>
<input
type="text"
placeholder="email"
name="contact_email_input"
defaultValue={email}
/>
<div>
<input type="submit" value="ok" />
<input type="reset" value="cancel" className="button" />
</div>
</form>
)
}
onSubmit = (evt) => {
// stop the page from refreshing
evt.preventDefault()
// target the form
const form = evt.target
// extract the two inputs from the form
const contact_name_input = form.contact_name_input
const contact_email_input = form.contact_email_input
// extract the values
const name = contact_name_input.value
const email = contact_email_input.value
// get the id and the update function from the props
const { id, updateContact } = this.props
// run the update contact function
updateContact(id,{ name, email })
// toggle back view mode
this.toggleEditMode()
}
...
Notice how the form's onReset
toggles the edit mode too, so when a user clicks "cancel", the form switches back the view mode.
We just need something to switch from edit mode to view mode. Add a new button:
<button className="success" onClick={this.toggleEditMode}>edit</button>
Stick this somewhere next to the delete button.
The whole component will look like

Almost done, now, to see it, go to App.js
, and do a little
// front/src/App.js
import Contact from './Contact'
at the top. Then, use it in the loop:
Replace where
...
{contacts_list.map(contact => (
<div key={contact.id}>
<span>
{contact.id} - {contact.name}
</span>
<button onClick={() => this.deleteContact(contact.id)} className="warning">x</button>
</div>
))}
...
by
//front/src/App.js
{contacts_list.map(contact => (
<Contact
key={contact.id}
id={contact.id}
name={contact.name}
email={contact.email}
updateContact={this.updateContact}
deleteContact={this.deleteContact}
/>
))}
Now you can:
insert a new contact in the database
delete a contact
update a contact
list all contacts
Congrats! You have a fully functional CRUD. This is not bad at all, ...for a start
Last updated
Was this helpful?