Lesson 5 - AJAX in React
In the last lesson, Completing the React Calculator, we completed a simple calculator in React.
We already know the basic work with the React javascript library, we know how components and JSX work. Today we will show you how to work with the API in React and how to use the popular AJAX technology, which we have already encountered in OOP courses.
Why use AJAX?
In previous lessons, we learned to work with components and data (numerical
inputs) entered directly by the user. But more often we expect a different
approach from the web application. The data is often not located on our
computer, but on the server. These are computers somewhere on
the Internet. The data is then accessible wherever we log in to the application,
which is not the case localStorage
AJAX technology
is used for communication with servers. Today we will show you how to
incorporate AJAX into React code.
AJAX
First, let's talk about what AJAX is. AJAX (Asynchronous JavaScript And XML) is a designation of a technology with which we can make HTTP requests from javascript (and therefore also from React). It's like entering a web address in the address bar of a browser. The browser sends an HTTP request and downloads the data at the given address (eg HTML code of the web page). AJAX allows us to do this directly in javascript code and especially in the background, without the page on which we are located having to load.
XML for AJAX can be misleading because with AJAX we can download and send any type of data, not just XML. So, for example, we already know JSON, text, HTML, images, videos, and more ...
It is important that AJAX does not crash the user interface of our
site until the server responds to the request. This would be done, for
example, by the confirm()
dialog, where we are waiting for the
user's response. The request is asynchronous. So we can
download larger pieces of data in the background and the user can still use the
page.
Use of AJAX in practice
So when is AJAX commonly used? We have 2 practical uses here:
- Creating a SPA (S ingle P age A plication) - A common website that we are used to, consists of several HTML pages to which links lead. When you click on the link, the browser deletes everything we see on the page and loads a new page. However, there are no such links in the single-page application. Instead, AJAX starts, which downloads new pages and background data. Then JavaScript inserts new content into the part of the page to be changed. So we are still on the same page. This can be more enjoyable than updating the whole window. It is more like the user interface of desktop applications. An example of a SPA is Gmail. Note that no matter what you click there, the page will never refresh completely, even if its address changes.
- Creating page plug-ins - It's not hard to come up with an example of a page that works with someone else's or our server. These are, for example, weather, chat, rating of posts, dynamic loading of comments when scrolling ... AJAX is also very suitable for web games where we want to store something, such as records in scores for creating rankings.
We usually do not use pure JavaScript to create SPA, but also some frameworks
such as Angular, Vue.js or React.
There is more Javascript code in similar applications and these frameworks will
make it easier for us to structure it better. That is why we will focus on him
now. If you need to refresh this issue more, return to the course of object-oriented programming in javascript
API
And what exactly is the API? The abbreviation stands for Application Programming Interface, translated as "application programming interface". Of course, we all know the graphical user interface (GUI), such as buttons and text boxes. They define how a person communicates with the program. The API defines how another program communicates with a program. However, this interface no longer consists of buttons, but, for example, of sets of functions, their URL addresses, and data structures that we send and receive.
We will work with the web API, so we will mainly deal with URLs to which we
will send AJAX requests. There is no need to look for anything complicated. You
can create a time.php
file with the code echo time();
on a PHP server. and you have a simple API for getting time.
But we will not program our
API, we will use ready-made ones instead. We'll get data on Pokémon.
Pokemon API
We will download the data from the pokeapi.co server. At this link, we can test the API directly by entering different URLs in the text box and listing the results.
The API itself is located at https://pokeapi.co/api/v2/
. This is
our starting URL, which will be the same in every AJAX request. By adding
additional parameters to the end of this URL, we will specify what the API
should return to us. So these are parameters.
Without API parameters, returns a list of objects:
They are not only Pokémon but also abilities or berries. Of course, we will
be interested in the pokemon
parameter, which will give us a list
of pokemon. You can try entering the address
https://pokeapi.co/api/v2/pokemon
in your browser:
We see that the API server responded with a list of Pokémon. If you notice that there are only the first 20, you are the masters of Pokémon. And if you thought the result was in JSON format, so do the masters of javascript:)
AJAX implementation in React
Let's try to display the names of these first twenty Pokémon. We'll show you how AJAX works in React.
Project creation
Let's create a new folder, for example pokemon/
and in it use
the command:
npx create-react-app .
Let's create a React application. The dot at the end of the command means
that we will create the application in the folder in which we are currently
located. As always, we have created a project that contains the folders
/public
, /node-modules
, and /src
. We will
be interested in the last component. We can delete all unnecessary files in it
and leave only the App.js
and index.js
files here.
App.js
For now, we will only work in the App.js
file, later, of course,
we will break down the "Pokémon Browser" into components. Let's start with the
libraries that we need to import into our component:
import React, { useState, useEffect } from 'react'; import axios from 'axios';
It is clear that we need the React
We will also need the
familiar React Hook useState
and the new useEffect
that we will introduce today. Finally, get through the terminal using the
command
npm i axios
we will install the axios
library. Axios is a
javascript library based on XMLHttpRequests, which is used to call AJAX and
which makes it easier for us to obtain data from external sources (such as API).
It's not the only way to work with the API, but it's one of the easier ones. It
nicely shows how working with the public API actually works.
The component itself will look like this:
function App() { const [data, setData] = useState([]); useEffect(() => { axios .get("https://pokeapi.co/api/v2/pokemon") .then((result) => setData(result.data.results)) .catch((error) => console.log(error)); }, []); return null; // we will add later } export default App;
First, we initialized the data
and setData
App
function using useState()
. Then it's Hook
useEffect()
. How does it work? Basically, it allows us to perform
various (side) effects in our functions. We actually tell React
that our component needs to do something after loading. React will remember the
function we passed (or our "effect") and call it later after performing
DOM updates. For example, we can call the API and get data from it.
You may be wondering why we call the useEffect()
function
inside a component? Placing it inside a component allows us to
access the properties of that component directly in the "effect" and we don't
need any other technology. React Hooks tries to make the most of javascript.
Where has a good solution been found, why invent new and unnecessarily
complicated ones?
Another important note about the useEffect()
function is that it
occurs after each page render. By default, it starts after the
first-page load and then with each update (it can, of course, be modified). In
addition, React guarantees that DOM updates have already taken place when it
launches "effects", so we no longer have to worry about whether a component has
joined (componentDidMount
lifecycle) or updated
(componentDidUpdate
lifecycle).
useEffect(() => { axios .get("https://pokeapi.co/api/v2/pokemon") .then((result) => setData(result.data.results)) .catch((error) => console.log(error)); }, []);
The use of axios itself is not complicated. We want to get the data,
so we choose the get()
method and insert the URL of the given API
into the parameters, in our case it is
https://pokeapi.co/api/v2/pokemon
. Once we get the data, we use the
then()
method to update the state of the data
variable
in the function (setData()
). Finally, it is good practice to use
the catch{}
block and have any errors written to the console.
Otherwise, in more complex projects, we could get stuck that the application
does not work and we do not know why.
Let's clarify once again Hook useEffect()
, or its parameters.
The mandatory parameter is a function (therefore we write
() => {...}
), which is called every time it is rendered.
[]
is optional, but very useful. This is an array of state
variables. If none of the variables are updated,
useEffect()
is skipped.
We got the data (we can make sure of that by listing it first in the
console), now it remains to print it in the return
.
map
functions will be used for this. The result might look like
this:
return ( <div className="container"> <ul> {data.map((pokemon) => ( <li> {pokemon.name} </li> ))} </ul> </div> );
We can try to turn on the server using the command:
npm start
Well, since we removed a few files that were dependencies of
index.js
and App.js
, we also need to modify
index.js
to not use non-existent styles, for example:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );
Now the application should compile and the browser will display this simple list of the first twenty Pokémon:
Developers tend to split into two camps. Some strongly use Axios, others
prefer the Fetch API (using the fetch()
method). In our second way,
our list of Pokémon could look like this:
import React, { useEffect, useState } from "react"; const App = () => { const [data, setData] = useState([]); const url = "https://pokeapi.co/api/v2/pokemon"; const fetchUrl = async () => { const { results } = await fetch(url).then((response) => response.json()); setData(results); }; useEffect(() => { fetchUrl(); }, []); return ( <div className="container"> <ul> {data.map((pokemon) => ( <li> {pokemon.name} </li> ))} </ul> </div> ); }; export default App;
If you had any problems or questions to the Fetch API, you can read the
lesson Asynchronous Requests Using the Fetch API
from the JavaScript OOP course.