If you are new to React.js my recent tutorial at https://app.wftutorials.com/ shows you how you can create a contacts application with react. I will go through some of the basics here but you can find the full walk-through here. I also did a video on it check that out here.
Lets get started.
The app I will be making has two main sections as shown in the picture below.

The File Structure
The are a few directory to take note.
- The public directory contains our main html template.
- The src directory contains our source JavaScript that defines how our application works.
- In the src directory we can pay attention to the
App.js
,home.js
,contacts.js
,create-contact.js
andview-contact.js
files.
You can find these files here. This is also the source github repo for our project.
Displaying our Data
In the picture above we can see two sections. We are now focusing on the right side. This is contacts.js
. Here we pull all our contacts within this component and display it to the user. Look at the full code here.
The first thing we do is get our contacts calling the getContacts
function.
constructor(props) {
super(props);
this.state = {items:this.props.contacts};
this.getContacts();
}
Within the getContacts
function we pull data from our server.
getContacts = () => {
fetch('http://dev.samples.com/getcontacts.php')
.then(rsp=>rsp.json())
.then(response =>{
this.setState({items:response.data});
console.log(response.data)
})
}
The getcontacts.php
is a simple file that returns records from a mysql
database. A sample of this file is shown below.
try {
$conn = new PDO($dsn, $user, $passwd);
if($id){
$query = $conn->prepare("SELECT * from contacts where id=?");
$query->execute([$id]);
$results = $query->fetchAll();
}else{
$results = $conn->query("SELECT * from contacts order by id desc");
}
foreach ($results as $result) {
array_push($data,[
"id" => $result["id"],
"name" => !empty($result["name"]) ? $result["name"] : "",
"email" => !empty($result["email"]) ? $result["email"] : "",
"phone" => !empty($result["phone"]) ? $result["phone"] : "",
"notes" => !empty($result["notes"]) ? $result["notes"] : ""
]);
}
} catch (Exception $e) {
echo $e->getMessage();
}
echo json_encode(['data'=>$data]);
In our getContacts
function we set the state to the response of our request.
this.setState({items:response.data});
So now the state is updated and we can display our records. We use the map function to iterate through our contacts within the render function.
{this.state.items.map(listitem => (
<li key={listitem.id} className="list-group-item">
<span onClick={()=>{this.props.viewContact(listitem)}}>
<i className="fa fa-user"></i> {listitem.name}</span>
<span>
{listitem.email ? " | " + listitem.email : ''}</span>
<button onClick={()=>{this.props.editContact(listitem)}} className="btn btn-primary btn-sm float-right">Edit</button>
</li>
))}
Add a new Contact
To add a new contact we need to pay attention to the create-contact.js
file. This is the component where we handle this process.
The render function of this component is important. Take note of the this.handleChange
function that is attached to the onChange
handler.
<form onSubmit={this.handleSubmit}>
<input name="id" type="hidden" className="form-control" value={this.currentid}/>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Contact Name</label>
<input name="name" type="text" className="form-control"
onChange={this.handleChange} placeholder="Enter contact name" value={this.state.currentContact.name} required/>
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Email</label>
<input name="email" className="form-control" value={this.state.currentContact.email}
onChange={this.handleChange} placeholder="email@test.com"/>
</div>
<button type="submit" className="btn btn-primary">Save contact</button>
</form>
In our component we deal with these. The handleChange
function ensures our states are always updated with the correct form values.
handleChange(e){
if(e.target.name == 'name'){
this.setState({currentContact : { name: e.target.value}})
}
if(e.target.name == 'email'){
this.setState({currentContact : { email: e.target.value}})
}
if(e.target.name == 'phone'){
this.setState({currentContact : { phone: e.target.value}})
}
if(e.target.name == 'notes'){
this.setState({currentContact: {notes: e.target.value}});
}
if(e.target.name == 'id'){
if(e.target.value != undefined || e.target.value != ''){
this.setState({currentContact : { id: e.target.value}});
console.log(e.target.value);
}
}
}
In our component constructor we need to bind these functions so we can access them within our render function.
constructor(props) {
super(props);
this.state = {currentContact: this.props.currentContact};
this.currentContact = this.props.currentContact;
this.currentid = this.props.currentContact.id;
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
When we submit this form we call the handleSubmit
function. This function sends the data to a saveContact
function which uploads our data to the server and saves it to a database.
handleSubmit(event) {
let formData = new FormData(event.target);
if (!event.target.checkValidity()) {
return;
}
this.props.saveContact(formData);
event.preventDefault();
event.target.reset();
this.clearCurrentContact();
}
The this.props.saveContact
indicates this function is being passed to the component. Lets see where this is happening.
Our home.js
is the main component or our parent component. Within it we can see our saveContact
function.
saveContact(data){
fetch("http://dev.samples.com/insertcontacts.php",
{
body: data,
method: "post"
}).then(()=>{ this.onContactAdded() });
}
Above we use the fetch
function specifying the method type as post
to send our data.
Parent and child components.
In my original article I went through the relationship of our components with each other. This is important to understand where some functions are created and where they are begin accessed. Building this application most of the functions we registered within home.js
component. Then I passed them in between the child components where necessary.

Lets just look at home.js
to see this happening. At the top of the file we import all the components we need.
import React, {Component} from 'react';
import Contacts from './contacts';
import CreateContacts from './create-contact';
import ContactView from "./view-contact";
Then we render these as we see fit. The contacts
component often stays the same. But we switch between viewing a contact and creating a contact components.
How to render components
Rendering a component is pretty easy after you import them. You can use them as html elements using the same name you imported them as.
To render the ContactView
we simple add this code below in the render function
<ContactView currentContact={this.state.currentContact}/>
Its that simple. CurrentContact is a prop that is passed from the main component to our ContactView
so within ContactView
we can access currentContact
using this.props.CurrentContact
.
We render the edit contact view in a similar fashion.
<Contacts editContact={this.editContact}
viewContact={this.viewContact}
refresh={this.state.refresh}
contacts={this.state.items}/>
In the above example you can see we are passing a lot of different props. Within the Contacts
component we have access to these variables and functions.
Conditionally Rendering Components
In our Home
component. We need to show two different views in two different conditions. So we conditionally render the correct view based on the state of our app. Let see how we accomplish this.

Above the variable isView
determines if we show a view or not. The above flowchart shows the logic that defines which component is being displayed on the left of the app. Let see what the code looks like

Conclusion
This is just a little of what React can do. Thanks for reading. You can view the full tutorial here – https://app.wftutorials.com/tutorial/148