React: Working with the Server(Part 1)

As a frontend developer, I majorly get to work with consuming and manipulating APIs. This article is going to be about working with the server — sending and retrieving data from the server.

Like I said in my previous article , these posts are a way to hold myself accountable while learning React, they are like my React journal. If you learn something from them, awesome 😃

Getting Started

We would create a simple phonebook that can add new contact details, edit contact, search through the contact list and also delete contacts. I won't do any serious setting up here, you can read this article for a walkthrough setting up.

We are going to use a tool called JSON SERVER , they provide a fake Rest API(so they say in their documentation).

We install JSON server as a development dependency by running

npm install json-server --save-dev

Then we add it to our package.json file, under the script's part

 "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "server": "json-server -p3001 --watch db.json"
  }

The -p3001 means it should run on port 3001, this is convenient since our npm start usually runs on port 3000. Now we can start the JSON server by running

npm run server

In the root folder, we create a file named db.json and copy the object below into the file

{
  "persons":[
    { 
      "name": "Netacci Adinnu", 
      "number": "0705348973",
      "id": 1
    },
    { 
      "name": "Lillian Is", 
      "number": "575840958",
      "id": 2
    },
    { 
      "name": "Eno Peter", 
      "number": "4758969007",
      "id": 3
    },
    { 
      "name": "Pope Matthews", 
      "number": "4667890054",
      "id": 4
    }
  ]
}

Now we have a basic backend database setup running on http://localhost:3001/persons. We can start creating our app.

Displaying Data

We want to get all the data in the db.json to display when the page loads, we use axios to fetch them. axios is installed by running

npm install axios

We create a persons state and set it to an empty array, then we use axios to fetch our data from our fake database URL [http://localhost:3001/persons](Link), the data gotten from there is updated to our empty array state.

import React, {useState, useEffect} from 'react'
import axios from 'axios'

const App=()=>{
    const [persons, setPersons] = useState([])

    useEffect(()=>{
          axios
         .get('http://localhost:3001/persons')
         .then(response=>{
           setPersons(response.data)
          })
    } ,[])
    return(
        <>
       </>
    )
}
 export default App

If we console.log(persons) we see our fake database listed.

To render them on the page we have to map through persons array. Remember we also have to assign a key.

    return(
        <> 
            {persons.map((person) => (
            <p key={person.id}>
              {person.name} {person.number}
            </p>
           ))}
       </>
    )

The page would display this

img.png

Handling Inputs

Now, we need to add a form to add new contact details

 return (
    <>
      <h2>PHONEBOOK</h2>
      <h3>Add New Contact</h3>
      <form >
        <div>
          name: <input type='text' />
        </div>
        <div>
          number: <input type='text' />
        </div>
        <button>ADD NEW</button>
      </form>
      <h3>Contact List</h3>
      {persons.map((person) => (
        <p key={person.id}>
          {person.name} {person.number}
        </p>
      ))}
    </>
  );

The page displays

img2.png

We want to submit our input values and display them on the contact list.

First, we create states for our name and number inputs

const [newName, setName] = useState('')
const [newNumber, setNumber] = useState('')

Then we create functions to handle our input values and the onSubmit. We also want the value of our input to be set to newName and newNumber state.

preventDefault method is an inbuilt method that prevents the form from submitting(refreshing the page) when the button is clicked.

  const handleSubmit = (e) => {
    e.preventDefault();
  };
 const handleNameChange = (e) => {
    setName(e.target.value);
  };
  const handleNumberChange = (e) => {
    setNumber(e.target.value);
  };
 <form onSubmit={handleSubmit}>
        <div>
          name: <input type='text' onChange={handleNameChange} value={newName}/>
        </div>
        <div>
          number: <input type='text' onChange={handleNumberChange} value={newNumber}/>
        </div>
        <button>ADD NEW</button>
</form>

In handleSubmit function, we create a new object that would accept name and number state and add it to the persons array. We make sure the number property accepts just number values by wrapping the value around the inbuilt Number function.

 const handleSubmit = (e) => {
    e.preventDefault();
    const addPerson = {
      name: newName,
      number: Number(newNumber),
      id : persons.length + 1
    }
   setPersons(persons.concat(addPerson));
  };

Now, when we add a new name and number we can see it on our page but it doesn't update at our backend.

Adding new Data to backend

We update data in the backend using the axios.post() method

  axios
      .post('http://localhost:3001/persons', addPerson)
      .then((response) => {
      setPersons(persons.concat(addPerson));
    });

When we add new data and check http://localhost:3001/persons , we can see that the name and number have been added to the list. After adding a contact to the contact list, we want to clear the input field, this can be done by setting the name and number state back to an empty string.

setName('')
setNumber('')

Now, we want to run a check to make sure we don't duplicate names on the list.

In the handleSubmit function, we map through the persons array and return an array of the name value for each person which we store in a variable called nameCheck, then we check if newName is in the nameCheck array — If it's there we return an alert saying the name already exists and it doesn't get added to the list.

 const nameCheck = persons.map((person) => person.name);
    nameCheck.includes(newName)
      ? alert(`${newName} already exists, Change it`)
      : axios
          .post('http://localhost:3001/persons', addPerson)
          .then((response) => {
            setPersons(persons.concat(addPerson));
            setName('');
            setNumber('');
          });
  };

We can also do the same check for numbers. It's easier to use the OR operator than just duplicating the whole code.

 const nameCheck = persons.map((person) => person.name);
 const numCheck = persons.map((person) => person.number);
    nameCheck.includes(newName) || numCheck.includes(newNumber)
      ? alert(`Contact already exists, Change it`)
      : axios
          .post('http://localhost:3001/persons', addPerson)
          .then((response) => {
            setPersons(persons.concat(addPerson));
            setName('');
            setNumber('');
          });

Now we can add new contacts to our phonebook and they are also updated in the backend.

I'm already exhausted from coding and typing 😃, So I'll divide this article into parts to not overwhelm myself.

In the next part, we'll search through the contact list, edit a contact, and maybe delete a contact if the article doesn't get so long.

Also, check out https://fullstackopen.com/en if you are trying to learn React

If there are better ways any of the codes on this article can be achieved, I would like to learn and once again pardon all grammatical errors, Grammarly can only do so much😁