Introduction to JSON Server (part II)

derick1530

Derick Zihalirwa

Posted on September 3, 2022

Introduction to JSON Server (part II)

As a frontend developer, when prototyping you need to know how to fetch data from your JSON Server, in this last part we are going to learn just that.Check out the first part

Prerequisite

  • To follow this article along, prior knowledge of React Hook,React Suspense API and JSON Server is essential.
  • Here is the GitHub repo (instructions are in the readme file)

Introduction

In this part, we are going to put into practice some request types (POST, GET, PUT, PATCH, and DELETE).
Before we start, in part 1 we were able to fetch data inside our database.json by playing with the URL, It will be the same but instead of making changes to the URL, we will write some codes.

Side note: we are using react Suspense API for data fetching. You can read more about it here as it is not under the scope of this article.

GET request

The application is running on localhost:3000
and the server on port localhost:7000;

GET ALL ITEMS
In your project repo navigate to fetchFici.js under web-client/src/page/

We are going to create a fetch function to get our data from JSON server.
in the first line above wrapPromise type enter this code:



const readAllFici = () => {
    return fetch("http://localhost:7000/data")
        .then(res => res.json())
        .catch(err => console.log(err))
}


Enter fullscreen mode Exit fullscreen mode

In createRousource file add readAllFici() in wrapPromise like this:



export const createResource = () => {
    return {
        data: wrapPromise(ReadAllFici())
    }
}


Enter fullscreen mode Exit fullscreen mode

In the first snippet we created a function and named it
readAllFici, we passed the json server url in the first parameter, we then got back a response from the server.

Next snippet we are passing fetch function to createResource which is part of the structure of using react Suspense.

Next, still in the same folder navigate to index.jsx
we will import createResource and it in our Screen component like this:



import { createResource } from './fetchFici';

const resource = createResource();
return (
   <Suspense fallback={<Spinner />}>
      <Screen resource={ressource} />
   </Suspense>
);


Enter fullscreen mode Exit fullscreen mode

In screen.jsx add this snippet:



const Screen = ({ resource }) => {
    const ficiData = resource.data.read()

    const displayFici = ficiData.map((item, index) => {
        return (
             ...
       )
...


Enter fullscreen mode Exit fullscreen mode

The above snippet we are getting the data sent by the server.
to see the result in your browser, refresh the page.

fetched data
We received all the items from the server and passed them inside the component.

GET A SINGLE ITEM
To get a single element we are going to change the fetch url to "/{the id of our item}"
Let's implement that.

First, create a new function to fetch item based on the id:



const readOneItem = (id) => {
    return fetch(`http://localhost:7000/data/${id}`)
        .then(res => res.json())
        .catch(err => console.log(err))
}


Enter fullscreen mode Exit fullscreen mode

Next, bellow createResource we create a new arrow function, the same as createResource but with a parameter, and that parameter will be received by readOneItem.



export const createResourceOnePost = (id) => {
    return {
        data: wrapPromise(readOneItem(id))
    }
}


Enter fullscreen mode Exit fullscreen mode

Next in singlePost.jsx we have two components one that receives the data and passes it through the component and one that displays it. Before that, we need to get the id of a single element. For our case, we used react-router-dom (you can check in App.jsx how we set up the routing).
In the second component we are going to get the id param from the URL, for that let's import useParams() and get the id:



import { useParams } from 'react-router-dom'

const { id } = useParams()


Enter fullscreen mode Exit fullscreen mode

Let's import createResourceOnePost and call the first component inside Suspense which takes ressource as parameter.



import { createResourceOnePost } from './fetchFici'
const resource = createResourceOnePost(id)
 return (
        <div className='border rounded-md bg-zinc-800 border-white p-4'>
            <p className='text-center text-3xl font-mono'>Fici Game</p>
            <Suspense fallback={<Spinner />}>
                <LoadData resource={resource} />
            </Suspense>
        </div>
    )


Enter fullscreen mode Exit fullscreen mode

Inside the child component let use the data passed in the parent component.



const LoadData = ({ resource }) => {
    const ficiData = resource.data.read()

    return (
        <div className='border bg-gray-900 flex flex-col space-y-4 justify-center items-center border-white h-80 m-4'>
            <p className="p-4 font-mono text-lg">{ficiData.name}</p>
            <span className='text-9xl shadow-2xl rounded-full'>{ficiData.symbol}</span>
        </div>
    )
    }


Enter fullscreen mode Exit fullscreen mode

The last thing we need to do is to navigate to the specific item.
In screen.jsx create a onClick inside displayFici



import { useNavigate } from 'react-router-dom';

const navigate = useNavigate()
const displayFici = ficiData.map((item, index) => {
        return (

            <tr className='border-b border-gray-500 cursor-pointer' onClick={() => {
                navigate(`/${item.id}`)
            }} key={index}>
                <td className='p-2'>{item.id}</td>
                <td className='p-2 text-center'>{item.name}</td>
                <td className='p-2'>
                    <span className='text-xl'>{item.symbol}</span>
                </td>
            </tr>

        )
    })


Enter fullscreen mode Exit fullscreen mode

Output

Fetch Single Item

POST METHOD

Let's add a third element to our list of items.
to do that we need to create a function, the same way we did for get request but instead of getting it, we will post (send) data to our JSON server.
so let's create that in fetchFici.js



export const postItem = () => {
    const doc = {
        name: 'Tornado',
        symbol: '🌪️'
    }
    return fetch('http://localhost:7000/data', {
        method: "POST",
        body: JSON.stringify(doc),
        headers: { 'content-Type': 'application/json' }
    })
}


Enter fullscreen mode Exit fullscreen mode

We created a doc object where we passed manually the item we want to add to our list, then to add that item inside our database.json we need to fetch, the first parameter is the URL this time it will receive a second parameter which is an object inside we pass the method which is POST for our case, the body, and the headers.

we do the same as we did for get request.
We import the function in screen.jsx component and it will be executed once a button is clicked.



import { postItem } from './fetchFici';

<div>
     <p className='text-center p-2'></p>
     <div className='text-center'>
        <button className='bg-sky-700 rounded-lg w-20 p-2' onClick={() => { postItem() }}>🌪️</button>
        <p className='font-mono'>Tornado</p>

     </div>
</div>


Enter fullscreen mode Exit fullscreen mode

Now if you click to the button and refresh the page, you will see an item have been added(read more about useEffecf here

add new item
if you check in our database.json instead of having 4 we now have 5 items. So far so good, now you know how to get and post data from the JSON server, next let's see how to Update and delete data.

UPDATE AND DELETE DATA

Update is almost the same thing as other types of requests, we are just changing the method to PUT or PATCH instead of POST.
side note: The difference between PUT and PATCH is that when you use PUT you have to specify all the properties inside your object body, if you need to update only one property you can make use of PATCH request.

So go ahead and create a new function and call it updatItem in fetchFici.js



export const updateItem = (id, body) => {
    return fetch(`http://localhost:7000/data/${id}`, {
        method: "PATCH",
        body: JSON.stringify(body),
        headers: { 'content-Type': 'application/json' }

    })
}


Enter fullscreen mode Exit fullscreen mode

In the code above we passed two parameters: the id for the item we want to update and the new name.

Now in singlePost.jsx let's add some lines of code.



import { updateItem } from './fetchFici'
import React, { useState } from 'react'


const LoadData = ({ resource }) => {
    const { id } = useParams();
   const [text, setText] = useState('');
    return (
   ...
            <span></span>
            <form onSubmit={updateHandler} className="flex flex-col">
                <input className='text-gray-700 text-center rounded-lg p-1' type="text" placeholder={ficiData?.name} value={text} onChange={(e) =>
                    setText(e.target.value)
                } />
                <button type='submit' className='p-4 bg-zinc-800 rounded-b-lg'>UPDATE</button>
            </form>
    )
}


Enter fullscreen mode Exit fullscreen mode

Output

ui update
Now if you change the name and click update, then refresh the page you should see the changes; in my case i updated Air to Vortex

name updated

DELETE ITEM

Now let's see how to delete an item.
You already know how to create a query function,
go ahead and create a function similar to updateItem
then remove all the object body as it is not needed, then change the request method to DELETE, don't forget to pass the id parameter, you need to know which item you want to delete from the list of items



import { deleteItem } from './fetchFici';

export const deleteItem = (id) => {
    return fetch(`http://localhost:7000/data/${id}`, {
        method: "DELETE"
    })
}


Enter fullscreen mode Exit fullscreen mode

Next let's add some code in screen.jsx



  <td>
      <button className='p-1' onClick={() => {
                        deleteItem(item.id)
                    }}><TbTrash className='text-red-600'/>
     </button>
</td>


Enter fullscreen mode Exit fullscreen mode

We imported deleteItem, inside displayFici we added a new td tag with a button, passed the deleteItem in onClick.

Output

Delete button

Click to one item then refresh the page you will see the item has been deleted.

item deleted

Conclusion

We have reached the end of our tutorial, We saw some types of requests that are useful for testing endpoints when prototyping.
For those types seen in the first part, I highly recommend you to go and try to implement them, and let me know in the comment if you encounter any challenges implementing them, I will be glad to help.
If you find this article helpful, don't forget to share it with your friends.

full source code GitHub repo
Learn more about React Suspense API here

Until next time, take care.

💖 💪 🙅 🚩
derick1530
Derick Zihalirwa

Posted on September 3, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related