ReactJS : Fetching Data From API
In this article, we'll expand our knowledge of React to further horizons. To get started, check out this article.
Why communicate with server?
For any application that stores or access data we need communication with server side. This makes the application more scalable and modifiable. Since React is basically a client-side tool, in this article we'll use tomcat as an Application Program Interface.There are several ways to fetch data from the server. Let's check out some of them.
We'll see how to get data of employees of a company stored in JSON form from the API.
Sending AJAX Request
AJAX stands for Asynchronous JavaScript And XML. It is a way of communicating with the server that helps in a more dynamic display of contents of a web application. Lets's see how it works.
In my machine, this is the folder structure :
{..path upto tomcat webapps folder..} /webapps/reactApp>employees.json
This is how I stored the data in employees.json :
[{"id":101,"name" : "Tom","age" : 45 }, {"id":102,"name" : "Dick", "age" : 50 }, {"id":103,"name" : "Harry", "age" : 25}]
For our JSX file :
C:\react\jsxEg\src>eg1.jsx
Note : This is just the folder structure I've used, you can create your own.
In eg1.jsx :
class Company extends React.Component { constructor(props) { super(props); this.state={"employees" : null}; this.getEmployeeData(); } getEmployeeData() { var employeeData; var xmlHttpRequest = new XMLHttpRequest(); let companyObject=this; let url = "http://localhost:8080/reactApp/employees.json"; xmlHttpRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { employeeData = JSON.parse(this.responseText); companyObject.setState({"employees" : employeeData}); } }; xmlHttpRequest.open("GET", url); xmlHttpRequest.send(); } render() { if(this.state.employees==null) return null; return ( <div> <h1>Employee Data </h1> <table border='2px'> <tr> <td> EmpId </td> <td> Name </td> <td> Age </td> </tr> { this.state.employees.map(employee=>( <tr> <td> {employee.id} </td> <td> {employee.name} </td> <td> {employee.age} </td> </tr> )) } </table> </div> ); } }
To transpile this jsx file to js file, move to jsxEg folder and write on command prompt :
.\node_modules\.bin\babel --plugins transform-react-jsx src -d {..path upto webapps folder..}\webapps\reactApp\js
Now create index.html in folder reactApp. In index.html write :
<!doctype html> <html lang='en'> <head> <title>Learning React</title> <script src='reactjs/react.production.min.js'></script> <script src='reactjs/react-dom.production.min.js'></script> <script src='js/eg1.js'></script> <script> window.addEventListener('load',function(){ let e=React.createElement(Company); let container=document.getElementById('mainContent'); ReactDOM.render(e,container); }); </script> </head> <body> <center> <h1> Fetching Data From Server Using JSX </h1> </center> <div id='mainContent'> </div> <center> <h1> Bye! </h1> </center> </body> </html>
To Check in browser, type in address bar :
http://localhost:8080/reactApp
This was my output :
In this example, we sent an AJAX request for the json on the server side. Steps to send an AJAX request:
1. Create an object of XMLHttpRequest.
2. To a property onreadystatechange of this class, assign a callback function. This function will get executed when property readyState changes.
3. In that function we have checked that if readyState is 4 (i.e. request is processed and response is ready) and status is 200 (OK), we have changed the state of the component by calling setState function. So the component is rerendered.
4. In open method, we specify the type of request, the url to where the request is to be sent and a third optional parameter(true/false), that defaults to true, and specifies whether the request sent is asynchronous or not.
5. If the type of request is "POST", we have to provide a data as an argument to the send method.
This was the traditional AJAX style which you might have used before.
Now let's learn something new.
Using Promises
Promises are designed to handle asynchronous computations. It returns a result at a later point of time. Using a promise we can handle an asynchronous operation's eventual success or failure. For success, we'll use then method which will be executed when the operation is successful. We can create a promise chain, by calling then method subsequently when the previous then also returns a promise. We use catch, for handling any error that might occur in the promise chain. Let's see this with the help of our example.
In eg1.jsx :
class Company extends React.Component { constructor(props) { super(props); this.state={"employees" : null,"error" : ""}; this.fetchEmployeeData(); } fetchEmployeeData() { let companyObject=this; fetch("http://localhost:8080/reactApp/employees.json").then(function(response){ response.json().then(function(data) { companyObject.setState({"employees" : data}); }); }).catch(function(error) { companyObject.setState({"error" : error}); }); } render() { if(this.state.error!="" || this.state.employees==null) { return ( <h2> Data cannot be fetched {this.state.error}</h2> ); } return ( <div> <h1>Employee Data </h1> <table border='2px'> <tr> <td> EmpId </td> <td> Name </td> <td> Age </td> </tr> { this.state.employees.map(employee=>( <tr> <td> {employee.id} </td> <td> {employee.name} </td> <td> {employee.age} </td> </tr> )) } </table> </div> ); } }
Note : The fetch method returns a promise, for which we have called then method which will be executed after resolution of the promise.
Transpile the jsx file to js file like before and without making any changes to index.html, check in browser. The output should same as before. We just used another approach for fetching data.
Now let's check out another method for fetching data.
The Async/Await Approach
This method is like a wrapper on Promises. It simplifies the long and complex chain of then and catch and makes our code cleaner, more readable and easier to implement.
async : This is a keyword which is written before the name of function in which we wish to do any asynchronous task. This wraps the return value of a function in a promise.
await : This keyword can only be used in a function that is declared async. It halts the JavaScript until the promise(before which await is written) is resolved. You'll understand better with an example.
In eg1.jsx : Modify the method fetchEmployeeData as follows :
async fetchEmployeeData() { let companyObject=this; try { let response = await fetch("http://localhost:8080/reactApp/employees.json"); let json = await response.json(); companyObject.setState({ "employees" : json }); }catch(error) { companyObject.setState({ "error" : error }); } }
Transpile the jsx file into js file like before and without making any changes to index.html check in browser. The output should be same as before.
Conclusion
We learnt three ways of fetching data from an API : the traditional AJAX style, promises and async/await. Implement these yourself and ask any doubts in the comment section.
Really helpful.
ReplyDeleteVery Informative .
ReplyDeletePerfectly explained!!
ReplyDeleteNicely Explained
ReplyDeleteOn point!
ReplyDeleteThoroughly explained.
ReplyDelete