ReactJS API Calls Example
In this article, we will take a look at making API Calls in a ReactJS application. Making API Calls to perform CRUD operations on data is a critical and important feature of most applications. We gain an understanding and learn the intricacies of achieving the same in with ReactJS. ReactJS has soared in popularity and has become the go-to library for Front end Development.
So without further ado let us get started and build an example ReactJS application.
I have used the following toolset and technologies to build the example in this article.
1. Tools and Technologies
create-react-app npm package from the folks at Facebook allows us to quickly generate a ReactJS application. We use it here to scaffold a starting point for our example. The latest ReactJS version is pulled down and used by create-react-app. ReactJS is a front end library and we use it here to show how to make API calls in a ReactJS application.
I have used Express to create a rudimentary API for the purposes of our example in Nodejs. concurrently allows us to run multiple commands concurrently like our server API and client-side code here. Visual Studio Code IDE is my editor of choice for front end development although you are free to follow along in an editor of your choice.
2. Project Structure
To generate our project we run the below command:
>npx create-react-app my-app
The npx command downloads a temporary copy of a package and runs it with the parameters provided. And once the above command completes running we should have the following project structure ready.
3. Server-side API
We will create a rudimentary API for use in our example. The API is backed by a sample dataset on which we will perform CRUD operations. The dataset represents a Cricket team of my favorite players. We will edit this list including add/remove players and update player names calling the server-side API each time. The changes will not be persistent as we will not use a backing database store for the sake of keeping things simple. Our dataset looks like below:
dataset.json
[ { "name": "Sachin Tendulkar" }, { "name": "Gautam Gambhir" }, { "name": "Sourav Ganguly" }, { "name": "Anil Kumble" }, { "name": "Virendar Sehwag" }, { "name": "Jasprit Bumrah" }, { "name": "Viraat Kohli" }, { "name": "Ravindra Jadeja" }, { "name": "Javagal Shreenath" }, { "name": "Kuldeep Yadav" }, { "name": "Rahul Dravid" }, { "name": "Venkatesh Prasad" } ]
To realize the Server-side API I have used Express and the code for the Server-side looks like below:
index.js
const express = require('express'); const app = express(); const bodyParser = require("body-parser"); const api = require('./teamController'); const cors = require('cors'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); app.use('/api', api()); const Port = process.env.PORT || 2019; app.listen(Port, () => { console.log(`Listening on ${Port}.`); });
The code for the team controller which handles the API request looks like below:
teamController.js
const router = require('express').Router(); let dataset = require('../dataset/dataset.js'); module.exports = () => { router.get('/', (req, res) => { return res.json(dataset); }); router.post('/addPlayer', (req, res) => { dataset.push(req.body); return res.json({ success: "success" }); }); router.patch('/updatePlayer/:oldName/:newName', (req, res) => { let player = dataset.map(p => p.name.toLowerCase() === req.params.oldName.toLowerCase()); player.name = req.params.newName; return res.json({ success: "success" }); }); router.delete('/deletePlayer/:name', (req, res) => { dataset = dataset.filter(p => p.name.toLowerCase() !== req.params.name.toLowerCase()); return res.json({ success: "success" }); }); return router; };
Now let’s move on to our client-side application and to making the actual calls to this API.
4. Client-side API Calls
Going about client-side development, I have created three ReactJS components namely, TeamPage, PlayerList, and Player. The TeamPage component hosts our UI. Whereas the PlayerList renders an unordered list of Players from our team. Each player is further passed onto an instance of the Player component to be displayed. Furthermore, the API calls are made from the TeamPage Component with the other two components acting as dumb or not so smart ones.
To make the actual API calls we use the fetch browser API. The code for each of the components discussed above looks like below.
TeamPage.js
import React, { useState, useEffect } from 'react'; import PlayerList from './PlayerList'; import dataService from '../Services/DataService'; function TeamPage(props) { const [team, setTeam] = useState(); useEffect(() => { dataService.getTeam() .then(resp => setTeam(resp)) .catch(err => console.log(err)); }, []); const deletePlayer = (name) => { dataService.deletePlayer(name) .then(r => { dataService.getTeam() .then(resp => setTeam(resp)) .catch(err => console.log(err)); }) .catch(err => console.log(err)); } const updatePlayer = (oldname, newname) => { dataService.updatePlayer(oldname, newname) .then(r => { dataService.getTeam() .then(resp => setTeam(resp)) .catch(err => console.log(err)); }) .catch(err => console.log(err)); } return <div style={{ display: 'flex', flexDirection: 'column', height: '100vh', width: '100vw', justifyContent: 'center', alignItems: 'center' }}> <PlayerList team={team} updatePlayer={updatePlayer} deletePlayer={deletePlayer} addPlayer={addPlayer} /> </div> } export default TeamPage;
PlayerList.js
import React, { useState } from 'react'; import Player from './Player'; function PlayerList(props) { const [newPlayer, setNewPlayer] = useState(""); const handleChange = ({ target }) => { setNewPlayer(target.value); } const handleClick = () => { if (!newPlayer) return; props.addPlayer(newPlayer); } return <> <input type="text" value={newPlayer} onChange={handleChange} /><button onClick={handleClick}>+</button> <ul> {props.team && props.team.map(p => <Player updatePlayer={props.updatePlayer} deletePlayer={props.deletePlayer} key={p.name} player={p} />)} </ul></> } export default PlayerList;
Player.js
import React, { useState } from 'react'; function Player(props) { const [editMode, setEditMode] = useState(false); const [playerName, setPlayerName] = useState(props.player.name); const handleChange = ({ target }) => { setPlayerName(target.value); } const saveChanges = ({ target }) => { props.updatePlayer(props.player.name, playerName); setEditMode(false); } const deletePlayer = () => { props.deletePlayer(playerName); } return <> {!editMode && <li>{playerName}</li>} {editMode && <><input value={playerName} onChange= {handleChange} /><br /></>} {!editMode && <><button onClick={() => { setEditMode(true) }}>Edit</button><button onClick= {deletePlayer}>X</button></>} {editMode && <button onClick={saveChanges}>Save</button>} </>; } export default Player;
The code for the dataService looks like below:
DataService.js
function getTeam() { return window.fetch('/api') .then(r => r.json()); } function addPlayer(player) { return window.fetch('/api/addPlayer', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(player) }) .then(r => r.json()); } function updatePlayer(oldname, newname) { return window.fetch(`/api/updatePlayer/${oldname}/${newname}` , { method: 'PATCH' }) .then(r => r.json()); } function deletePlayer(name) { return window.fetch(`/api/deletePlayer/${name}`, { method: 'DELETE' }) .then(r => r.json()); } export default { getTeam, updatePlayer, addPlayer, deletePlayer }
Now let us see our application in action.
5. Running the application
To run our application we need to run the following command
/my-app>npm start
This command as it is setup will launch both, our Server-side API as well as the ReactJS application using concurrently. The result should be as below:
This wraps up our look at API Calls example in a ReactJS Application.
6. Download the Source Code
You can download the full source code of this example here: ReactJS API Calls Example