REACT Routing
https://teamtreehouse.com/library/posting-data-with-fetch
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DoggoSelect</title>
<link href="https://fonts.googleapis.com/css?family=Bree+Serif|Open+Sans:400,700" rel="stylesheet">
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<header>
<h1 class="logo">DoggoSelect</h1>
</header>
<div class="container">
<label for="breeds">Select a Breed</label>
<select class="u-full-width" id="breeds"></select>
<div class="card"></div>
<form>
<label for="name">Name</label>
<input class="u-full-width" id="name" type="text">
<label for="comment">Comment</label>
<textarea class="u-full-width" id="comment"></textarea>
<button type="submit" id="submit">Submit</button>
</form>
<p>Made with <3 by <a href="https://teamtreehouse.com/">Treehouse</a></p>
</div>
<script src="js/app.js"></script>
</body>
</html>
NOTES SET 1
/* 1. variables that select items from the html - these are what we are going to give api data to */
/*
https://javascript.info/fetch
https://www.geeksforgeeks.org/react-hook-form-create-basic-reactjs-registration-and-login-form/?ref=gcse
https://www.pluralsight.com/guides/process-an-api-response-in-react
https://www.javascripttutorial.net/javascript-fetch-api/
*/
const select = document.getElementById('breeds');
const card = document.querySelector('.card');
const form = document.querySelector('form');
/*
BASIC
fetch('myapi.com/endpoint')
.then ( do something once previous promise is fulfilled - gets response from server)
.then ( do something once previous promise is fulfilled)
BASIC #2
https://www.geeksforgeeks.org/how-to-fetch-data-from-an-api-in-reactjs/
ADDING CREDENTIALS: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included
https://tmmwiki.com/index.php/NATS5_REST_API_Overview#Authentication
This example requires npm and the request module which can be installed via npm by: 'npm install request'
fetch('myapi.com/endpoint')
data is returend in json - so inorder to use it we have to parse it to json first -
use response interface and convert response to json -
SEE: OTHER METHODS: https://developer.mozilla.org/en-US/docs/Web/API/Response#methods
.then(response => response.json())
.then ( do something once previous promise is fulfilled)
+++++++++++++++++
STEP 2 - check with console log
FETCH EXAMPLES: https://developer.mozilla.org/en-US/docs/Web/API/Response#examples
fetch('myapi.com/endpoint') /* TEST copy paste into colsole log to see response (if open api)
.then ( do something once previous promise is fulfilled)
THEN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
ADD NEXT:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
https://developer.mozilla.org/en-US/docs/Web/API/Response
- chain then method to the fetch pass it a function (using arrow function) that takes a response via a paramater (we are calling that response) - logs to console log to start
*/
// ------------------------------------------
// FETCH FUNCTIONS
// ------------------------------------------
/* https://dog.ceo/dog-api/documentation */
/* area where you add link from api for endpoint step 1 - get random image
response keyword - json is what api gives you back */
/* step 2 */
fetch('https://dog.ceo/api/breeds/image/random')/* check by copy paste into console */
.then(response => response.json())
/* check response - .then(data => console.log(data))
see response - and that the info we want is logged as "message"
update data call */
.then(data => generateImage(data.message))
/* step 4 get breeds list NEW FETCH REQUEST*/
fetch('https://dog.ceo/api/breeds/list') /* call endpoint using fetch method*/
.then(response => response.json()) /* chain a then method that converts data in response to json */
// .then(data => console.log(data)); this is used to test and get what values are retunred
/* get a message array - that we have to insert inot options - and put in select menu */
.then(data => generateOptions(data.message))
// ------------------------------------------
// HELPER FUNCTIONS
// ------------------------------------------
/* step 4 - get the message data into the select options pull down
const select = document.getElementById('breeds'); geting info in here
*/
function generateOptions(data) {
const options = data.map(item =>`
<option value='${item}'>${item}</option>
`).join(''); // calling join on the map items - putting '' empty quotes removes all the commas that came over with theapi
select.innerHTML = options;
}
/* step 3 called from fetch functions area - could be written there - but easier to break out
data created in fetch funct */
function generateImage(data) {
const html= `
<img src='${data}' alt>
<p>Click to view images of ${select.value}s</p>
`;
card.innerHTML = html;
}
// ------------------------------------------
// EVENT LISTENERS
// ------------------------------------------
// ------------------------------------------
// POST DATA
// ------------------------------------------
NOTES SET 2
/* SEE 4/start app-notes.js for notes up to this point */
const select = document.getElementById('breeds');
const card = document.querySelector('.card');
const form = document.querySelector('form');
// ------------------------------------------
// FETCH FUNCTIONS
// ------------------------------------------
/* FINAL 4 - app.js - notesbelow ***************/
/* step 5 - creat reusable fetch func tion */
/* this is the resuable function for multiple requests */
function fetchData(url) { // name of wrapper function - fetchData that takes paramater url
return fetch(url) // function returns fetch method - into which we are also passing the url paramater
.then(res => res.json()) // chain then method that parses json response.
}
/* step 6 - simplify fetch functions using fetchData funtion from step 5*/
/* these can be simplified using fetchData
fetch('https://dog.ceo/api/breeds/list')
.then(response => response.json())
.then(data => generateOptions(data.message))
fetch('https://dog.ceo/api/breeds/image/random')
.then(response => response.json())
.then(data => generateImage(data.message))
*/
fetchData('https://dog.ceo/api/breeds/list')
.then(data => generateOptions(data.message))
fetchData('https://dog.ceo/api/breeds/image/random')
.then(data => generateImage(data.message))
// ------------------------------------------
// HELPER FUNCTIONS
// ------------------------------------------
function generateOptions(data) {
const options = data.map(item => `
<option value='${item}'>${item}</option>
`).join('');
select.innerHTML = options;
}
function generateImage(data) {
const html = `
<img src='${data}' alt>
<p>Click to view images of ${select.value}s</p>
`;
card.innerHTML = html;
}
/* step 7 create a new fetch request */
/* next step is to make it possible to click on card div and see other images of breed - also will update text to say "click to view more dog breed name" */
function fetchBreedImage(){
const breed = select.value; // breed is connected to the select drop down - gets the selected value - USED TO MODIFY FETCH REQUEST BELOW
/* selectin img and p elements in card */
const img = card.querySelector('img');
const p = card.querySelector('p');
/* new fetch request for all images of breed - we have to use a tempalte literal to insert the selected breen into api link to get correct images
https://dog.ceo/api/breed/hound/images/random
url above needs to be made dynamic
*/
// fetchData('https://dog.ceo/api/breed/hound/images/random') use new fetchData function - sstart with basic random img url - REPLACE WITH BREED VARIABLE
fetchData(`https://dog.ceo/api/breed/${breed}/images/random`)
/* add a them methof to tell it to use new image that caem in from api */
.then(data => {
img.src = data.message;
img.alt = breed;
p.textContent = `Click to view more ${breed}s`;
})
}
// ------------------------------------------
// EVENT LISTENERS
// ------------------------------------------
/* step 8 - add event listeners to catch page chagnes */
/* this is where you tell it to watch for changes*/
select.addEventListener('change', fetchBreedImage); //adding an event listener to select element - telling it to change the fetchBreedImage function as callback
card.addEventListener('click', fetchBreedImage); // card is watching for a click that will cause it to update to value of fetchBreedImAge - callback
// ------------------------------------------
// POST DATA
// ------------------------------------------
NOTES SET 3 (5-Handling errors lesson)
/* SEE 4/start app-notes.js for notes up to this point */
const select = document.getElementById('breeds');
const card = document.querySelector('.card');
const form = document.querySelector('form');
// ------------------------------------------
// FETCH FUNCTIONS
// ------------------------------------------
/* FINAL 4 - app.js - ***************/
/* Start 5-Handling errors NOTES */
function fetchData(url) {
return fetch(url)
//step 11 - add console log response data output - so you can see all repsonse data
//.then(res => console.log(res))
//step 13 - change the colsole log response to the # 12 check status
.then(checkStatus)
/* so if the response is OK - it can continute through the rest of the fetch using the response data it was getting before - but now it is checked befoer we push it thorugh.*/
.then(res => res.json())
/* STEP 10 - add catch to handle errors for all fetch requtrest*/
.catch(error => console.log('Sorry problem encountered in:',error))
}
fetchData('https://dog.ceo/api/breeds/list')
.then(data => generateOptions(data.message))
/* STEP 9 - add catch to handle errors test in 1 version */
// .catch(error => console.log('Sorry problem encountered in:',error))
fetchData('https://dog.ceo/api/breeds/image/random')
.then(data => generateImage(data.message))
// ------------------------------------------
// HELPER FUNCTIONS
// ------------------------------------------
// step 12 - handing errors with checkStatus helper funciton
function checkStatus(response) { //pass teh function the response data
if (response.ok) { //if the resonse is OK
// return Promise.resolve(givenvalueinhere) - returns a Promise that resolves to a value you give it
return Promise.resolve(response); // if ok - then resolve to the value of response
} else { // if response if not ok
return Promise.reject(new Error(response.statusText)); // promise is rejected - activates catch; reject needs to be passed the reject object. So create a new Error object and pass it the response.status that you got from api.
}
}
function generateOptions(data) {
const options = data.map(item => `
<option value='${item}'>${item}</option>
`).join('');
select.innerHTML = options;
}
function generateImage(data) {
const html = `
<img src='${data}' alt>
<p>Click to view images of ${select.value}s</p>
`;
card.innerHTML = html;
}
function fetchBreedImage() {
const breed = select.value;
const img = card.querySelector('img');
const p = card.querySelector('p');
fetchData(`https://dog.ceo/api/breed/${breed}/images/random`)
.then(data => {
img.src = data.message;
img.alt = breed;
p.textContent = `Click to view more ${breed}s`;
})
}
// ------------------------------------------
// EVENT LISTENERS
// ------------------------------------------
select.addEventListener('change', fetchBreedImage);
card.addEventListener('click', fetchBreedImage);
// ------------------------------------------
// POST DATA
// ------------------------------------------
Promise.all handling multiple requests
/* start - part 5 - has notes to this part up to step 13 */
const select = document.getElementById('breeds');
const card = document.querySelector('.card');
const form = document.querySelector('form');
// ------------------------------------------
// FETCH FUNCTIONS
// ------------------------------------------
function fetchData(url) {
return fetch(url)
.then(checkStatus)
.then(res => res.json())
.catch(error => console.log('Looks like there was a problem!', error))
}
/* step 14*/
/* Promise.all - you can put multiiple functions togethre and it will waite uniil all resolve before moving on
it can be passed an array - or just the fetch callls
*/
// useful if you HAVE to get user profile info - to use for other parts*/
Promise.all {[
fetchData('https://dog.ceo/api/breeds/list'),
fetchData('https://dog.ceo/api/breeds/image/random') // so now it will wait for both to resolve
// it returns a single Promoise.all response - with the data in the order you added it to the function - to see what you get first use console log
//step 16
// .then(data => console.log(data))
// this will give you the order in teh array and their array index
// user the array index to assign each value to a variable
//step 17 - overwrite step 16
.then(data => {
const breedList = data[0].message; // assign data index 0 the message value to breedList
const randomImage = data[1].message; // assign data index 1
//step 18
generateOptions(breedList);
generateImage(randomImage);//now we pass those variable to the previous functions
})
/* step 19
remove previous calls
fetchData('https://dog.ceo/api/breeds/list')
.then(data => generateOptions(data.message))
fetchData('https://dog.ceo/api/breeds/image/random')
.then(data => generateImage(data.message))
*/
// ------------------------------------------
// HELPER FUNCTIONS
// ------------------------------------------
function checkStatus(response) {
if (response.ok) {
return Promise.resolve(response);
} else {
return Promise.reject(new Error(response.statusText));
}
}
function generateOptions(data) {
const options = data.map(item => `
<option value='${item}'>${item}</option>
`).join('');
select.innerHTML = options;
}
function generateImage(data) {
const html = `
<img src='${data}' alt>
<p>Click to view images of ${select.value}s</p>
`;
card.innerHTML = html;
}
function fetchBreedImage() {
const breed = select.value;
const img = card.querySelector('img');
const p = card.querySelector('p');
fetchData(`https://dog.ceo/api/breed/${breed}/images/random`)
.then(data => {
img.src = data.message;
img.alt = breed;
p.textContent = `Click to view more ${breed}s`;
})
}
// ------------------------------------------
// EVENT LISTENERS
// ------------------------------------------
select.addEventListener('change', fetchBreedImage);
card.addEventListener('click', fetchBreedImage);
// ------------------------------------------
// POST DATA
// ------------------------------------------
Post Data from Form to API with Fetch
/* see start step 6 - promise.all */
/* left off at step 19 */
const select = document.getElementById('breeds');
const card = document.querySelector('.card');
const form = document.querySelector('form');
// ------------------------------------------
// FETCH FUNCTIONS
// ------------------------------------------
function fetchData(url) {
return fetch(url)
.then(checkStatus)
.then(res => res.json())
.catch(error => console.log('Looks like there was a problem!', error))
}
Promise.all([
fetchData('https://dog.ceo/api/breeds/list'),
fetchData('https://dog.ceo/api/breeds/image/random')
])
.then(data => {
const breedList = data[0].message;
const randomImage = data[1].message;
generateOptions(breedList);
generateImage(randomImage);
})
// ------------------------------------------
// HELPER FUNCTIONS
// ------------------------------------------
function checkStatus(response) {
if (response.ok) {
return Promise.resolve(response);
} else {
return Promise.reject(new Error(response.statusText));
}
}
function generateOptions(data) {
const options = data.map(item => `
<option value='${item}'>${item}</option>
`).join('');
select.innerHTML = options;
}
function generateImage(data) {
const html = `
<img src='${data}' alt>
<p>Click to view images of ${select.value}s</p>
`;
card.innerHTML = html;
}
function fetchBreedImage() {
const breed = select.value;
const img = card.querySelector('img');
const p = card.querySelector('p');
fetchData(`https://dog.ceo/api/breed/${breed}/images/random`)
.then(data => {
img.src = data.message;
img.alt = breed;
p.textContent = `Click to view more ${breed}s`;
})
}
// ------------------------------------------
// EVENT LISTENERS
// ------------------------------------------
select.addEventListener('change', fetchBreedImage);
card.addEventListener('click', fetchBreedImage);
//step 21 - add event listeners to wire form up to the function / api
form.addEventListener('submit',postData); // add event listern on form - passing submit event - postData function is the callback
/* STEP 22 - GET is the default method - so what is happening is that we are GETTING all the data from teh api -= not posting it*/
// ------------------------------------------
// POST DATA
// ------------------------------------------
// step 20 - create a post data function - it takes paramater "e" for event
/*
function postData(e) {
e.preventDefault(); // have to stop the dfault behavior (sumitting) untiul everythig is ready
// now add values form input fields (name) and comment text area (comment)
//const name;
//const comment;
// add the values of the fields to the constnats
const name = document.getElementById('name').value;
const comment = document.getElementById('comment').value;
//use the https://jsonplaceholder.typicode.com/
//as a place test to send api data
fetch('https://jsonplaceholder.typicode.com/comments') // calling to the comments area of hte api
.then(checkStatus) // check that connection is good
.then(res => res.json) // parse to json
.then(data => console.log(data)) //log the return data to the console
//}
*/
// step 23 - how to POST data using fetch*/
function postData(e) {
e.preventDefault();
const name = document.getElementById('name').value;
const comment = document.getElementById('comment').value;
// fetch can accept a second object it required method, headers, and body
fetch('https://jsonplaceholder.typicode.com/comments', {
method: 'POST', // type of request - use uppercase
headers: {
'Content-Type': 'application/json'
}, // headers aer contained within an oject.
/*
// to send - you have to convert values to a json string
//body: JSON.stringify({ name: name, comment: comment // so we pass the values name and comment with their values name and comment into the stringify event
*/
/* step 24 - if the value and name of object are teh same - you can use shorthand*/
body: JSON.stringify({ name, comment })
})
.then(checkStatus)
.then(res => res.json()) //res.json does not work you ahve to call a funciton
.then(data => console.log(data)) //step 25 - once 24 is in place - cosole log should show up the data you are sending to server
}
/* step 25 - make a config function out of POST
call that function instead of straight to post method -
makes it more readable - easier ot manage
const config = {
method: 'POST', // type of request - use uppercase
headers: {
'Content-Type': 'application/json'
}, // headers aer contained within an oject.
body: JSON.stringify({ name, comment })
}
*
fetch('https://jsonplaceholder.typicode.com/comments', config)
.then(checkStatus)
.then(res => res.json()) //res.json does not work you ahve to call a funciton
.then(data => console.log(data)) //step 25 - once 24 is in place - cosole log should show up the data you are sending to server
}
*/
// above is final step with post as config
Sending a request with credentials included (using fetch)
HEADERS::: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#headers
Supplying your own request object
Instead of passing a path to the resource you want to request into the fetch()
call, you can create a request object using the Request()
constructor, and pass that in as a fetch()
method argument:
const myHeaders = new Headers();
const myRequest = new Request('flowers.jpg', {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default',
});
fetch(myRequest)
.then(response => response.blob())
.then(myBlob => {
myImage.src = URL.createObjectURL(myBlob);
});
Request()
accepts exactly the same parameters as the fetch()
method. You can even pass in an existing request object to create a copy of it:
const anotherRequest = new Request(myRequest, myInit);
This is pretty useful, as request and response bodies can only be used once. Making a copy like this allows you to effectively use the request/response again while varying the init
options if desired. The copy must be made before the body is read.
Note: There is also a clone()
method that creates a copy. Both methods of creating a copy will fail if the body of the original request or response has already been read, but reading the body of a cloned response or request will not cause it to be marked as read in the original.
Headers
The Headers
interface allows you to create your own headers object via the Headers()
constructor. A headers object is a simple multi-map of names to values:
const content = 'Hello World';
const myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/plain');
myHeaders.append('Content-Length', content.length.toString());
myHeaders.append('X-Custom-Header', 'ProcessThisImmediately');
Basic Authentication – Django REST Framework
https://www.geeksforgeeks.org/basic-authentication-django-rest-framework/?ref=gcse
https://www.geeksforgeeks.org/how-to-fetch-data-from-an-api-in-reactjs/
How to fetch data from an API in ReactJS ?
- Difficulty Level : Medium
- Last Updated : 18 Aug, 2021
ReactJS: ReactJS is a declarative, efficient, and flexible JavaScript library for building user interfaces. It’s ‘V’ in MVC. ReactJS is an open-source, component-based front-end library responsible only for the view layer of the application. It is maintained by Facebook.
API: API is an abbreviation for Application Programming Interface which is a collection of communication protocols and subroutines used by various programs to communicate between them. A programmer can make use of various API tools to make its program easier and simpler. Also, an API facilitates the programmers with an efficient way to develop their software programs.
Approach: In this article, we will know how we fetch the data from API (Application Programming Interface). For the data, we have used the API endpoint from http://jsonplaceholder.typicode.com/users we have created the component in App.js and styling the component in App.css. From the API we have target “id”, “name”, “username”, “email” and fetch the data from API endpoints. Below is the stepwise implementation of how we fetch the data from an API in react. We will use the fetch function to get the data from the API.
Step by step implementation to fetch data from an api in react.
Step 1: Create React Project
npm create-react-app MY-APP
Step 2: Change your directory and enter your main folder charting as
cd MY-APP
Step 3: API endpoint
https://jsonplaceholder.typicode.com/users
API
Step 4: Write code in App.js to fetch data from API and we are using fetch function.
Project Structure: It will look the following.
Project Structure
Example:
- App.js
import React from "react";
import './App.css';
class App extends React.Component {
// Constructor
constructor(props) {
super(props);
this.state = {
items: [],
DataisLoaded: false
};
}
// ComponentDidMount is used to
// execute the code
componentDidMount() {
fetch(
"https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((json) => {
this.setState({
items: json,
DataisLoaded: true
});
})
}
render() {
const { DataisLoaded, items } = this.state;
if (!DataisLoaded) return <div>
<h3> Pleses wait some time.... </h3> </div> ;
return (
<div className = "App">
<h3> Fetch data from an api in react </h3> {
items.map((item) => (
<ol key = { item.id } >
User_Name: { item.username },
Full_Name: { item.name },
User_Email: { item.email }
</ol>
))
}
</div>
);
}
}
export default App;
Write code in App.css for styling the app.js file.
- App.css
.App {
text-align: center;
color: Green;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Step to run the application: Open the terminal and type the following command.
npm start
Output: Open the browser and our project is shown in the URL http://localhost:3000/
https://www.geeksforgeeks.org/how-to-navigate-on-path-by-button-click-in-react-router/)
How to pass data from child component to its parent in ReactJS ?21, Feb 21
How to pass data from one component to other component in ReactJS ?23, May 21
Different ways to fetch data using API in React, Nov 21
How to send one or more files to an API using axios in ReactJS?13, Jan 21
How to fetch data from APIs using Asynchronous await in ReactJS ?09, Jul 21
Consuming a REST API ( Github Users ) using Fetch – React Client08, Nov 21
How to navigate on path by button click in react router ?
How to change state continuously after a certain amount of time in React?
Consuming a GraphQL API using fetch – React Client02, Dec 21
How to perform fetch and send with Firestore using ReactJS ?06, Apr 21
COVID-19 Tracker using ReactJS and real time API08, Sep 21
How to connect ReactJS with flask API ?26, Feb
How to delete multiple cache data in ReactJS ?26, Apr 21
How to clear complete cache data in ReactJS ?26, Apr 21
How to delete specific cache data in ReactJS ?23, Apr 21
How to store multiple cache data in ReactJS ?23, Apr 21
How to use x-grid-data-generator Module in ReactJS ?23, Apr 21
How to store single cache data in ReactJS ?23, Apr 21
How to get complete cache data in ReactJS ?23, Apr 21
How to get single cache data in ReactJS ?23, Apr 21
How to get multiple cache data in ReactJS ?23, Apr 21
ReactJS Data Binding19, May 21
How to get meta data of files in firebase storage using ReactJS ?02, Jun 21
How to push data into firebase Realtime Database using ReactJS ?17, Jun 21
ReactJS UI Ant Design Data Display Component Complete Reference10, Jan
ReactJS UI Ant Design Data Entry Component Complete Reference10, Jan
Fetch
JavaScript can send network requests to the server and load new information whenever it’s needed.
For example, we can use a network request to:
- Submit an order,
- Load user information,
- Receive latest updates from the server,
- …etc.
…And all of that without reloading the page!
There’s an umbrella term “AJAX” (abbreviated Asynchronous JavaScript And XML) for network requests from JavaScript. We don’t have to use XML though: the term comes from old times, that’s why that word is there. You may have heard that term already.
There are multiple ways to send a network request and get information from the server.
The fetch()
method is modern and versatile, so we’ll start with it. It’s not supported by old browsers (can be polyfilled), but very well supported among the modern ones.
The basic syntax is:
let promise = fetch(url, [options])
url
– the URL to access.options
– optional parameters: method, headers etc.
Without options
, this is a simple GET request, downloading the contents of the url
.
The browser starts the request right away and returns a promise that the calling code should use to get the result.
Getting a response is usually a two-stage process.
First, the promise
, returned by fetch
, resolves with an object of the built-in Response class as soon as the server responds with headers.
At this stage we can check HTTP status, to see whether it is successful or not, check headers, but don’t have the body yet.
The promise rejects if the fetch
was unable to make HTTP-request, e.g. network problems, or there’s no such site. Abnormal HTTP-statuses, such as 404 or 500 do not cause an error.
We can see HTTP-status in response properties:
status
– HTTP status code, e.g. 200.ok
– boolean,true
if the HTTP status code is 200-299.
For example:
let response = await fetch(url);
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let json = await response.json();
} else {
alert("HTTP-Error: " + response.status);
}
Second, to get the response body, we need to use an additional method call.
Response
provides multiple promise-based methods to access the body in various formats:
response.text()
– read the response and return as text,response.json()
– parse the response as JSON,response.formData()
– return the response asFormData
object (explained in the next chapter),response.blob()
– return the response as Blob (binary data with type),response.arrayBuffer()
– return the response as ArrayBuffer (low-level representation of binary data),- additionally,
response.body
is a ReadableStream object, it allows you to read the body chunk-by-chunk, we’ll see an example later.
For instance, let’s get a JSON-object with latest commits from GitHub:
let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits';
let response = await fetch(url);
let commits = await response.json(); // read response body and parse as JSON
alert(commits[0].author.login);
Or, the same without await
, using pure promises syntax:
fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits')
.then(response => response.json())
.then(commits => alert(commits[0].author.login));
To get the response text, await response.text()
instead of .json()
:
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
let text = await response.text(); // read response body as text
alert(text.slice(0, 80) + '...');
As a show-case for reading in binary format, let’s fetch and show a logo image of “fetch” specification (see chapter Blob for details about operations on Blob
):
let response = await fetch('/article/fetch/logo-fetch.svg');
let blob = await response.blob(); // download as Blob object
// create <img> for it
let img = document.createElement('img');
img.style = 'position:fixed;top:10px;left:10px;width:100px';
document.body.append(img);
// show it
img.src = URL.createObjectURL(blob);
setTimeout(() => { // hide after three seconds
img.remove();
URL.revokeObjectURL(img.src);
}, 3000);
Important:
We can choose only one body-reading method.
If we’ve already got the response with response.text()
, then response.json()
won’t work, as the body content has already been processed.
let text = await response.text(); // response body consumed
let parsed = await response.json(); // fails (already consumed)
Response headers
The response headers are available in a Map-like headers object in response.headers
.
It’s not exactly a Map, but it has similar methods to get individual headers by name or iterate over them:
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits');
// get one header
alert(response.headers.get('Content-Type')); // application/json; charset=utf-8
// iterate over all headers
for (let [key, value] of response.headers) {
alert(`${key} = ${value}`);
}
Request headers
To set a request header in fetch
, we can use the headers
option. It has an object with outgoing headers, like this:
let response = fetch(protectedUrl, {
headers: {
Authentication: 'secret'
}
});
…But there’s a list of forbidden HTTP headers that we can’t set:
Accept-Charset
,Accept-Encoding
Access-Control-Request-Headers
Access-Control-Request-Method
Connection
Content-Length
Cookie
,Cookie2
Date
DNT
Expect
Host
Keep-Alive
Origin
Referer
TE
Trailer
Transfer-Encoding
Upgrade
Via
Proxy-*
Sec-*
These headers ensure proper and safe HTTP, so they are controlled exclusively by the browser.
POST requests
To make a POST
request, or a request with another method, we need to use fetch
options:
method
– HTTP-method, e.g.POST
,body
– the request body, one of:
- a string (e.g. JSON-encoded),
FormData
object, to submit the data asmultipart/form-data
,Blob
/BufferSource
to send binary data,- URLSearchParams, to submit the data in
x-www-form-urlencoded
encoding, rarely used.
The JSON format is used most of the time.
For example, this code submits user
object as JSON:
let user = {
name: 'John',
surname: 'Smith'
};
let response = await fetch('/article/fetch/post/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
let result = await response.json();
alert(result.message);
Please note, if the request body
is a string, then Content-Type
header is set to text/plain;charset=UTF-8
by default.
But, as we’re going to send JSON, we use headers
option to send application/json
instead, the correct Content-Type
for JSON-encoded data.
Sending an image
We can also submit binary data with fetch
using Blob
or BufferSource
objects.
In this example, there’s a <canvas>
where we can draw by moving a mouse over it. A click on the “submit” button sends the image to the server:
<body style="margin:0">
<canvas id="canvasElem" width="100" height="80" style="border:1px solid"></canvas>
<input type="button" value="Submit" onclick="submit()">
<script>
canvasElem.onmousemove = function(e) {
let ctx = canvasElem.getContext('2d');
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
};
async function submit() {
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
let response = await fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
});
// the server responds with confirmation and the image size
let result = await response.json();
alert(result.message);
}
</script>
</body>
Please note, here we don’t set Content-Type
header manually, because a Blob
object has a built-in type (here image/png
, as generated by toBlob
). For Blob
objects that type becomes the value of Content-Type
.
The submit()
function can be rewritten without async/await
like this:
function submit() {
canvasElem.toBlob(function(blob) {
fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
})
.then(response => response.json())
.then(result => alert(JSON.stringify(result, null, 2)))
}, 'image/png');
}
Summary
A typical fetch request consists of two await
calls:
let response = await fetch(url, options); // resolves with response headers
let result = await response.json(); // read body as json
Or, without await
:
fetch(url, options)
.then(response => response.json())
.then(result => /* process result */)
Response properties:
response.status
– HTTP code of the response,response.ok
–true
if the status is 200-299.response.headers
– Map-like object with HTTP headers.
Methods to get response body:
response.text()
– return the response as text,response.json()
– parse the response as JSON object,response.formData()
– return the response asFormData
object (multipart/form-data
encoding, see the next chapter),response.blob()
– return the response as Blob (binary data with type),response.arrayBuffer()
– return the response as ArrayBuffer (low-level binary data),
Fetch options so far:
method
– HTTP-method,headers
– an object with request headers (not any header is allowed),body
– the data to send (request body) asstring
,FormData
,BufferSource
,Blob
orUrlSearchParams
object.
In the next chapters we’ll see more options and use cases of fetch
.
Tasks
Fetch users from GitHub
Create an async function getUsers(names)
, that gets an array of GitHub logins, fetches the users from GitHub and returns an array of GitHub users.
The GitHub url with user information for the given USERNAME
is: https://api.github.com/users/USERNAME
.
There’s a test example in the sandbox.
Important details:
- There should be one
fetch
request per user. - Requests shouldn’t wait for each other. So that the data arrives as soon as possible.
- If any request fails, or if there’s no such user, the function should return
null
in the resulting array.
https://www.pluralsight.com/guides/process-an-api-response-in-react
Process an API Response in React
- Nov 17, 2020
- 5 Min read
- 31,570 Views
Web DevelopmentClient-side FrameworksReactFront End Web Development
Top
Introduction
Working with backend services such as a REST API is one of the most common tasks of a frontend developer. No matter what React app you're building, at some point, you'll probably want to make a request to a database server or an endpoint and grab some data to display to the user. For instance, if you're building a social media app and you want to display comments on a certain post to the user, you need to make a request to a dedicated API to fetch all the comments and then process it further in your app.
In this guide, you'll learn how to call an API to fetch its response in your React app.
Initial Setup
Let's run through an example to get a better understanding of how you can call the API response. Create an empty React app by running:
1npx create-react-app react-api-response
shell
Next, install the Axios library. Axios is a library that simplifies the process of interacting with APIs.
1npm i axios
shell
The endpoint you're going to use in this example is https://jsonplaceholder.typicode.com/comments. It's a free REST API endpoint that returns some dummy data you can play around with. You can choose any other such API or use your own API as well.
Creating State to Store Response
Whatever response you get from an API, you need to store it locally within that component so you can process it further. Import the useState
hook from React to create a piece of state
to store the response.
1import React,{useState} from 'react';
javascript
Create a state variable comments
and a hook to set the value of this state variable setComments
using the useState
hook.
1const [comments,setComments]=useState([])
javascript
Since the comments returned will be an array of objects with each object representing a single comment, the initial value of comments
is an empty array.
Calling API and Processing Response
Usually, you want to fetch data inside a component when its entire DOM loads. In other words, when your App
component first mounts on the DOM, you need to make a request to the API. In React, this can be carried out via a component lifecycle method called componentDidMount()
, which is fired when the component first loads on the DOM. A simple hooks implementation can be carried out by firing an asynchronous function using the async
keyword inside useEffect()
and passing an empty array as a parameter, as shown below.
1useEffect(() => {
2 fetchComments();
3}, [])
javascript
Create the fetchComments()
method, as shown below.
1const fetchComments=async()=>{
2 const response=await Axios('https://jsonplaceholder.typicode.com/comments');
3 setComments(response.data)
4}
javascript
Inside fetchComments()
, call the API by passing the endpoint to Axios and store the response in a variable using the await
keyword. All the comments from the endpoint can be referred to by calling the data
property on the response object
to set the state
. You can check if you correctly appended comments to your state
using the following piece of code:
1useEffect(() => {
2 console.log(comments)
3}, [comments])
javascript
Outputting Response on the DOM
So far in this guide, you have called the API response and stored it inside your state
. You can process it further using the state
. For instance, you can cycle through the comments
and render each comment
on the DOM, as shown below.
1 return (
<div className="App">
{
comments && comments.map(comment=>{
return(
<div key={comment.id} style={{alignItems:'center',margin:'20px 60px'}}>
<h4>{comment.name}</h4>
<p>{comment.email}</p>
</div>
)
})
}
</div>
);
jsx
Have a look at the entire App
component, which calls the API on mounting, sets the response to the component's state
, and outputs it on the DOM.
1import './App.css';
import Axios from 'axios'
import React,{useState,useEffect} from 'react';
function App() {
const [comments,setComments]=useState([])
useEffect(() => {
fetchComments();
}, [])
useEffect(() => {
console.log(comments)
}, [comments])
const fetchComments=async()=>{
const response=await Axios('https://jsonplaceholder.typicode.com/comments');
setComments(response.data)
}
return (
<div className="App">
{
comments && comments.map(comment=>{
return(
<div key={comment.id} style={{alignItems:'center',margin:'20px 60px'}}>
<h4>{comment.name}</h4>
<p>{comment.email}</p>
</div>
)
})
}
</div>
);
}
export default App;
javascript
Conclusion
You can interact with an API in different ways by making different kinds of requests from your app. For instance, you can make a POST
request to add a new comment by storing it in the database. However, to process any dynamic data from a server on loading a component, you should make requests in componentDidMount()
and store them inside your state
, as demonstrated. Instead of simply outputting this data, you can explore more options, such as filtering or sorting data, adding pagination, etc.
Consuming REST APIs In React With Fetch And Axios
QUICK SUMMARY ↬ If you’re a React developer who’d like to learn how you can start consuming APIs in your React applications, then this article is for you. Shedrack Akintayo explains what a REST API is and how to build a simple application that consumes a REST API by using both Fetch API and Axios.
Consuming REST APIs in a React Application can be done in various ways, but in this tutorial, we will be discussing how we can consume REST APIs using two of the most popular methods known as Axios (a promise-based HTTP client) and Fetch API (a browser in-built web API). I will discuss and implement each of these methods in detail and shed light on some of the cool features each of them have to offer.
APIs are what we can use to supercharge our React applications with data. There are certain operations that can’t be done on the client-side, so these operations are implemented on the server-side. We can then use the APIs to consume the data on the client-side.
APIs consist of a set of data, that is often in JSON format with specified endpoints. When we access data from an API, we want to access specific endpoints within that API framework. We can also say that an API is a contractual agreement between two services over the shape of request and response. The code is just a byproduct. It also contains the terms of this data exchange.
In React, there are various ways we can consume REST APIs in our applications, these ways include using the JavaScript inbuilt fetch()
method and Axios which is a promise-based HTTP client for the browser and Node.js.
Note: A good knowledge of ReactJS, React Hooks, JavaScript and CSS will come in handy as you work your way throughout this tutorial.
Let’s get started with learning more about the REST API.
More after jump! Continue reading below ↓
Meet Image Optimization, Addy Osmani’s brand new practical guide to optimizing and delivering high-quality images on the web. From formats and compression to delivery and maintenance: everything in one single 528-pages book.
What Is A REST API #
A REST API is an API that follows what is structured in accordance with the REST Structure for APIs. REST stands for “Representational State Transfer”. It consists of various rules that developers follow when creating APIs.
THE BENEFITS OF REST APIS #
- Very easy to learn and understand;
- It provides developers with the ability to organize complicated applications into simple resources;
- It easy for external clients to build on your REST API without any complications;
- It is very easy to scale;
- A REST API is not language or platform-specific, but can be consumed with any language or run on any platform.
AN EXAMPLE OF A REST API RESPONSE #
The way a REST API is structured depends on the product it’s been made for — but the rules of REST must be followed.
The sample response below is from the Github Open API. We’ll be using this API to build a React app later on in this tutorial.
{
"login": "hacktivist123",
"id": 26572907,
"node_id": "MDQ6VXNlcjI2NTcyOTA3",
"avatar_url": "https://avatars3.githubusercontent.com/u/26572907?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/hacktivist123",
"html_url": "https://github.com/hacktivist123",
"followers_url": "https://api.github.com/users/hacktivist123/followers",
"following_url": "https://api.github.com/users/hacktivist123/following{/other_user}",
"gists_url": "https://api.github.com/users/hacktivist123/gists{/gist_id}",
"starred_url": "https://api.github.com/users/hacktivist123/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/hacktivist123/subscriptions",
"organizations_url": "https://api.github.com/users/hacktivist123/orgs",
"repos_url": "https://api.github.com/users/hacktivist123/repos",
"events_url": "https://api.github.com/users/hacktivist123/events{/privacy}",
"received_events_url": "https://api.github.com/users/hacktivist123/received_events",
"type": "User",
"site_admin": false,
"name": "Shedrack akintayo",
"company": null,
"blog": "https://sheddy.xyz",
"location": "Lagos, Nigeria ",
"email": null,
"hireable": true,
"bio": "☕ Software Engineer | | Developer Advocate🥑|| ❤ Everything JavaScript",
"public_repos": 68,
"public_gists": 1,
"followers": 130,
"following": 246,
"created_at": "2017-03-21T12:55:48Z",
"updated_at": "2020-05-11T13:02:57Z"
}
Copy
The response above is from the Github REST API when I make a GET
request to the following endpoint https://api.github.com/users/hacktivist123
. It returns all the stored data about a user called hacktivist123. With this response, we can decide to render it whichever way we like in our React app.
Consuming APIs Using The Fetch API #
The fetch()
API is an inbuilt JavaScript method for getting resources from a server or an API endpoint. It’s similar to XMLHttpRequest
, but the fetch API provides a more powerful and flexible feature set.
It defines concepts such as CORS and the HTTP Origin header semantics, supplanting their separate definitions elsewhere.
The fetch()
API method always takes in a compulsory argument, which is the path or URL to the resource you want to fetch. It returns a promise that points to the response from the request, whether the request is successful or not. You can also optionally pass in an init options object as the second argument.
Once a response has been fetched, there are several inbuilt methods available to define what the body content is and how it should be handled.
THE DIFFERENCE BETWEEN THE FETCH API AND JQUERY AJAX #
The Fetch API is different from jQuery Ajax in three main ways, which are:
- The promise returned from a
fetch()
request will not reject when there’s an HTTP error, no matter the nature of the response status. Instead, it will resolve the request normally, if the response status code is a 400 or 500 type code, it’ll set the ok status. A request will only be rejected either because of network failure or if something is preventing the request from completing fetch()
will not allow the use of cross-site cookies i.e you cannot carry out a cross-site session usingfetch()
fetch()
will also not send cookies by default unless you set thecredentials
in the init option.
PARAMETERS FOR THE FETCH API #
resource
This is the path to the resource you want to fetch, this can either be a direct link to the resource path or a request objectinit
This is an object containing any custom setting or credentials you’ll like to provide for your
fetch()
request. The following are a few of the possible options that can be contained in the
init
object:
method
This is for specifying the HTTP request method e.g GET, POST, etc.headers
This is for specifying any headers you would like to add to your request, usually contained in an object or an object literal.body
This is for specifying a body that you want to add to your request: this can be aBlob
,BufferSource
,FormData
,URLSearchParams
,USVString
, orReadableStream
objectmode
This is for specifying the mode you want to use for the request, e.g.,cors
,no-cors
, orsame-origin
.credentials
This for specifying the request credentials you want to use for the request, this option must be provided if you consider sending cookies automatically for the current domain.
BASIC SYNTAX FOR USING THE FETCH() API #
A basic fetch request is really simple to write, take a look at the following code:
fetch('https://api.github.com/users/hacktivist123/repos')
.then(response => response.json())
.then(data => console.log(data));
Copy
In the code above, we are fetching data from a URL that returns data as JSON and then printing it to the console. The simplest form of using fetch() often takes just one argument which is the path to the resource you want to fetch and then return a promise containing the response from the fetch request. This response is an object.
The response is just a regular HTTP response and not the actual JSON. In order to get the JSON body content from the response, we’d have to change the response to actual JSON using the json() method on the response.
USING FETCH API IN REACT APPS #
Using the Fetch API in React Apps is the normal way we’d use the Fetch API in javascript, there is no change in syntax, the only issue is deciding where to make the fetch request in our React app. Most fetch requests or any HTTP request of any sort is usually done in a React Component.
This request can either be made inside a Lifecycle Method if your component is a Class Component or inside a useEffect()
React Hook if your component is a Functional Component.
For example, In the code below, we will make a fetch request inside a class component, which means we’ll have to do it inside a lifecycle method. In this particular case, our fetch request will be made inside a componentDidMount
lifecycle method because we want to make the request just after our React Component has mounted.
import React from 'react';
class myComponent extends React.Component {
componentDidMount() {
const apiUrl = 'https://api.github.com/users/hacktivist123/repos';
fetch(apiUrl)
.then((response) => response.json())
.then((data) => console.log('This is your data', data));
}
render() {
return <h3>my Component has Mounted, Check the browser 'console' </h3>;
}
}
export default myComponent;
Copy
In the code above, we are creating a very simple class component that makes a fetch request that logs the final data from the fetch request we have made to the API URL into the browser console after the React component has finished mounting.
The fetch()
method takes in the path to the resource we want to fetch, which is assigned to a variable called apiUrl
. After the fetch request has been completed it returns a promise that contains a response object. Then, we are extracting the JSON body content from the response using the json()
method, finally we log the final data from the promise into the console.
-
A React Data Grid that makes a developer's life easier? Yes, there is one: the KendoReact Grid.
GET A DATA GRID!
Let’s Consume A REST API With Fetch Method #
In this section, we will be building a simple react application that consumes an external API, we will be using the Fetch method to consume the API.
The simple application will display all the repositories and their description that belongs to a particular user. For this tutorial, I’ll be using my GitHub username, you can also use yours if you wish.
The first thing we need to do is to generate our React app by using create-react-app
:
npx create-react-app myRepos
Copy
The command above will bootstrap a new React app for us. As soon as our new app has been created, all that’s left to do is to run the following command and begin coding:
npm start
Copy
If our React is created properly we should see this in our browser window when we navigate to localhost:3000
after running the above command.
In your src
folder, create a new folder called component
. This folder will hold all of our React components. In the new folder, create two files titled List.js and withListLoading.js. These two files will hold the components that will be needed in our app.
The List.js file will handle the display of our Repositories in the form of a list, and the withListLoading.js file will hold a higher-order component that will be displayed when the Fetch request we will be making is still ongoing.
In the List.js file we created inside the components
folder, let’s paste in the following code:
import React from 'react';
const List = (props) => {
const { repos } = props;
if (!repos || repos.length === 0) return <p>No repos, sorry</p>;
return (
<ul>
<h4 className='list-head'>Available Public Repositories</h4>
{repos.map((repo) => {
return (
<li key={repo.id} className='list'>
<span className='repo-text'>{repo.name} </span>
<span className='repo-description'>{repo.description}</span>
</li>
);
})}
</ul>
);
};
export default List;
Copy
The code above is a basic React list component that would display the data, in this case, the repositories name and their descriptions in a list.
Now, Let me explain the code bit by bit.
const { repos } = props;
Copy
We are initializing a prop for the component called repos.
if (repos.length === 0 || !repos) return <p>No repos, sorry</p>;
Copy
Here, all we are doing is making a conditional statement that will render a message when the length of the repos we get from the request we make is equal to zero.
return (
<ul>
<h4 className='list-head'>Available Public Repositories</h4>
{repos.map((repo) => {
return (
<li key={repo.id} className='list'>
<span className='repo-text'>{repo.name} </span>
<span className='repo-description'>{repo.description}</span>
</li>
);
})}
</ul>
);
Copy
Here, we are mapping through each of the repositories that will be provided by the API request we make and extracting each of the repositories names and their descriptions then we are displaying each of them in a list.
export default List;
Copy
Here we are exporting our List
component so that we can use it somewhere else.
In the withListLoading.js file we created inside the components folder, let’s paste in the following code:
import React from 'react';
function WithListLoading(Component) {
return function WihLoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return (
<p style={{ textAlign: 'center', fontSize: '30px' }}>
Hold on, fetching data may take some time :)
</p>
);
};
}
export default WithListLoading;
Copy
The code above is a higher-order React component that takes in another component and then returns some logic. In our case, our higher component will wait to check if the current isLoading
state of the component it takes is true
or false
. If the current isLoading
state is true, it will display a message Hold on, fetching data may take some time 🙂. Immediately the isLoading
state changes to false
it’ll render the component it took in. In our case, it’ll render the List component.
In your App.js* file inside the src** folder, let’s paste in the following code:
import React, { useEffect, useState } from 'react';
import './App.css';
import List from './components/List';
import withListLoading from './components/withListLoading';
function App() {
const ListLoading = withListLoading(List);
const [appState, setAppState] = useState({
loading: false,
repos: null,
});
useEffect(() => {
setAppState({ loading: true });
const apiUrl = `https://api.github.com/users/hacktivist123/repos`;
fetch(apiUrl)
.then((res) => res.json())
.then((repos) => {
setAppState({ loading: false, repos: repos });
});
}, [setAppState]);
return (
<div className='App'>
<div className='container'>
<h3>My Repositories</h3>
</div>
<div className='repo-container'>
<ListLoading isLoading={appState.loading} repos={appState.repos} />
</div>
<footer>
<div className='footer'>
Built{' '}
<span role='img' aria-label='love'>
💚
</span>{' '}
with by Shedrack Akintayo
</div>
</footer>
</div>
);
}
export default App;
Copy
Our App.js is a functional component that makes use of React Hooks for handling state and also side effects. If you’re not familiar with React Hooks, read my Getting Started with React Hooks Guide.
Let me explain the code above bit by bit.
import React, { useEffect, useState } from 'react';
import './App.css';
import List from './components/List';
import withListLoading from './components/withListLoading';
Copy
Here, we are importing all the external files we need and also the components we created in our components folder. We are also importing the React Hooks we need from React.
const ListLoading = withListLoading(List);
const [appState, setAppState] = useState({
loading: false,
repos: null,
});
Copy
Here, we are creating a new component called ListLoading
and assigning our withListLoading
higher-order component wrapped around our list component. We are then creating our state values loading
and repos
using the useState()
React Hook.
useEffect(() => {
setAppState({ loading: true });
const user = `https://api.github.com/users/hacktivist123/repos`;
fetch(user)
.then((res) => res.json())
.then((repos) => {
setAppState({ loading: false, repos: repos });
});
}, [setAppState]);
Copy
Here, we are initializing a useEffect()
React Hook. In the useEffect()
hook, we are setting our initial loading state to true, while this is true, our higher-order component will display a message. We are then creating a constant variable called user
and assigning the API URL we’ll be getting the repositories data from.
We are then making a basic fetch()
request like we discussed above and then after the request is done we are setting the app loading state to false and populating the repos state with the data we got from the request.
return (
<div className='App'>
<div className='container'>
<h3>My Repositories</h3>
</div>
<div className='repo-container'>
<ListLoading isLoading={AppState.loading} repos={AppState.repos} />
</div>
</div>
);
}
export default App;
Copy
Here we are basically just rendering the Component we assigned our higher-order component to and also filling the isLoading
prop and repos
prop with their state value.
Now, we should see this in our browser, when the fetch request is still being made, courtesy of our withListLoading
higher-order component:
Now, when the fetch request has completed successfully, we should see the repositories displayed in a list format as below:
Now, let’s style our project a little bit, in your App.css file, copy and paste this code.
@import url('https://fonts.googleapis.com/css2?family=Amiri&display=swap');
:root {
--basic-color: #23cc71;
}
.App {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Amiri', serif;
overflow: hidden;
}
.container {
display: flex;
flex-direction: row;
}
.container h3 {
font-size: 60px;
text-align: center;
color: var(--basic-color);
}
.repo-container {
width: 50%;
height: 700px;
margin: 50px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
overflow: scroll;
}
@media screen and (max-width: 600px) {
.repo-container {
width: 100%;
margin: 0;
box-shadow: none;
}
}
.repo-text {
font-weight: 600;
}
.repo-description {
font-weight: 600;
font-style: bold;
color: var(--basic-color);
}
.list-head {
text-align: center;
font-weight: 800;
text-transform: uppercase;
}
.footer {
font-size: 15px;
font-weight: 600;
}
.list {
list-style: circle;
}
Copy
So in the code above, we are styling our app to look more pleasing to the eyes, we have assigned various class names to each element in our App.js file and thus we are using these class names to style our app.
Once we’ve applied our styling, our app should look like this:
Now our app looks much better. 😊
So that’s how we can use the Fetch API to consume a REST API. In the next section, we’ll be discussing Axios and how we can use it to consume the same API in the same App.
-
Belmont goes for gold at National ADDY Awards
Take a look at our student Regional award-winning work
SEE WINNING WORK
Consuming APIs With Axios #
Axios is an easy to use promise-based HTTP client for the browser and node.js. Since Axios is promise-based, we can take advantage of async and await for more readable and asynchronous code. With Axios, we get the ability to intercept and cancel request, it also has a built-in feature that provides client-side protection against cross-site request forgery.
FEATURES OF AXIOS #
- Request and response interception
- Streamlined error handling
- Protection against XSRF
- Support for upload progress
- Response timeout
- The ability to cancel requests
- Support for older browsers
- Automatic JSON data transformation
MAKING REQUESTS WITH AXIOS #
Making HTTP Requests with Axios is quite easy. The code below is basically how to make an HTTP request.
// Make a GET request
axios({
method: 'get',
url: 'https://api.github.com/users/hacktivist123',
});
// Make a Post Request
axios({
method: 'post',
url: '/login',
data: {
firstName: 'shedrack',
lastName: 'akintayo'
}
});
Copy
The code above shows the basic ways we can make a GET and POST HTTP request with Axios.
Axios also provides a set of shorthand method for performing different HTTP requests. The Methods are as follows:
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
For example, if we want to make a similar request like the example code above but with the shorthand methods we can do it like so:
// Make a GET request with a shorthand method
axios.get('https://api.github.com/users/hacktivist123');
// Make a Post Request with a shorthand method
axios.post('/signup', {
firstName: 'shedrack',
lastName: 'akintayo'
});
Copy
In the code above, we are making the same request as what we did above but this time with the shorthand method. Axios provides flexibility and makes your HTTP requests even more readable.
MAKING MULTIPLE REQUESTS WITH AXIOS #
Axios provides developers the ability to make and handle simultaneous HTTP requests using the axios.all()
method. This method takes in an array of arguments and it returns a single promise object that resolves only when all arguments passed in the array have resolved.
For example, we can make multiple requests to the GitHub api using the axios.all()
method like so:
axios.all([
axios.get('https://api.github.com/users/hacktivist123'),
axios.get('https://api.github.com/users/adenekan41')
])
.then(response => {
console.log('Date created: ', response[0].data.created_at);
console.log('Date created: ', response[1].data.created_at);
});
Copy
The code above makes simultaneous requests to an array of arguments in parallel and returns the response data, in our case, it will log to the console the created_at
object from each of the API responses.
Let’s Consume A REST API With Axios Client #
In this section, all we’ll be doing is replacing fetch()
method with Axios in our existing React Application. All we need to do is to install Axios and then use it in our App.js file for making the HTTP request to the GitHub API.
Now let’s install Axios in our React app by running either of the following:
With NPM:
npm install axios
Copy
With Yarn:
yarn add axios
Copy
After installation is complete, we have to import axios into our App.js. In our App.js we’ll add the following line to the top of our App.js file:
import axios from 'axios'
Copy
After adding the line of code our App.js all we have to do inside our useEffect()
is to write the following code:
useEffect(() => {
setAppState({ loading: true });
const apiUrl = 'https://api.github.com/users/hacktivist123/repos';
axios.get(apiUrl).then((repos) => {
const allRepos = repos.data;
setAppState({ loading: false, repos: allRepos });
});
}, [setAppState]);
Copy
You may have noticed that we have now replaced the fetch API with the Axios shorthand method axios.get
to make a get
request to the API.
axios.get(apiUrl).then((repos) => {
const allRepos = repos.data;
setAppState({ loading: false, repos: allRepos });
});
Copy
In this block of code, we are making a GET request then we are returning a promise that contains the repos data and assigning the data to a constant variable called allRepos
. We are then setting the current loading state to false and also passing the data from the request to the repos state variable.
If we did everything correctly, we should see our app still render the same way without any change.
So this is how we can use Axios client to consume a REST API.
Fetch Vs Axios #
In this section, I will be listing our certain features and then I’ll talk about how well Fetch and Axios support these features.
- Basic Syntax Both Fetch and Axios have very simple syntaxes for making requests. But Axios has an upper hand because Axios automatically converts a response to JSON, so when using Axios we skip the step of converting the response to JSON, unlike Fetch() where we’d still have to convert the response to JSON. Lastly, Axios shorthand methods allow us to make specific HTTP Requests easier.
- Browser Compatibility One of the many reasons why developers would prefer Axios over Fetch is because Axios is supported across major browsers and versions unlike Fetch that is only supported in Chrome 42+, Firefox 39+, Edge 14+, and Safari 10.1+.
- Handling Response Timeout
Setting a timeout for responses is very easy to do in Axios by making use of the
timeout
option inside the request object. But in Fetch, it is not that easy to do this. Fetch provides a similar feature by using theAbortController()
interface but it takes more time to implement and can get confusing. - Intercepting HTTP Requests Axios allows developers to intercept HTTP requests. HTTP interceptors are needed when we need to change HTTP requests from our application to the server. Interceptors give us the ability to do that without having to write extra code.
- Making Multiple Requests Simultaneously
Axios allows us to make multiple HTTP requests with the use of the
axios.all()
method ( I talked about this above).fetch()
provides the same feature with the use of thepromise.all()
method, we can make multiplefetch()
requests inside it.
Conclusion #
Axios and fetch()
are all great ways of consuming APIs but I advise you to use fetch()
when building relatively small applications and make use of Axios when building large applications for scalability reasons. I hope you enjoyed working through this tutorial, you could always read more on Consuming REST APIs with either Fetch or Axios from the references below. If you have any questions, you can leave it in the comments section below and I’ll be happy to answer every single one.
- The supporting repo for this article is available on Github.
RELATED RESOURCES #
- “REST API Structure,”
- “Understanding And Using REST APIs,” Zell Liew
- “CORS,”
- “HTTP Headers,”
- “Fetch API,” Mozilla Developer Network
- “Using Axios And React,” Paul Halliday
- “How To Make HTTP Requests Like A Pro With Axios,” Faraz Kelhini