Date 3 : React Js and REST API
Goal 1: Call REST API from ReactJs
Pre-Requirement
Understand React application life cycle from here.
Development Steps
Step 1: In order to make an HTTP request, I will install axios npm package using the following command. For using — save will add this dependency in my package.json file
npm install — save axios
Step 2: import axios in index.js file as following
var axios = require('axios');
Step 3: Create a new React component called ‘CardList’ and initialize its initial state. So we have a variable called ‘persons’ which is an empty list.
var CardList = React.createClass({
getInitialState: function() {
return {
persons: []
}
},
... ... ... ...
... ... ... ...
});
Step 4: Make the REST call inside componentDidMount method
componentDidMount is executed after first render only on the client side. This is where AJAX requests and DOM or state updates should occur. This method is also used for integration with other JavaScript frameworks and any functions with delayed execution like setTimeoutor setInterval. We are using it to update the state so we can trigger the other lifecycle methods.
For making an HTTP GET call, I will use public API from Random User Generator (I just love you guys! This API is awesome to play with). this.props.source will be used as the rest API url which will be passed from the template.
this.props.source = http://api.randomuser.me/?results=5
This API call will return 5 person document as json object as following
As results is the json object passed by the response, therefore persons array will be populated as follows ‘result.data.results’
var CardList = React.createClass({
... ... ... ...
... ... ... ...
componentDidMount: function() {
// Is there a React-y way to avoid rebinding `this`? fat arrow?
var th = this;
this.serverRequest =
axios.get(this.props.source)
.then(function(result) {
th.setState({
persons: result.data.results
});
})
},
... ... ... ...
... ... ... ...
});
Step 5: Export module for Card component developed in last story by adding the following line at the end of the file
module.exports = Card;
Therefore app/components/card.js look like as following
var React = require('react');
var ReactDOM = require('react-dom');var AvatarHeader = React.createClass({
render: function() {
var headerstyle = {
height: 150,
backgroundColor: "#9BC345",
};
return(
<div style={headerstyle}> </div>
);
}
});
var Avatar = React.createClass({
render: function() {
var user_photo = {
position:"relative",
background: "#fff",
padding: 5,
width: 130,
height: 130,
borderRadius: 75,
borderWidth: 1 ,
birderStyle:'solid',
left: 250,
bottom: 50
};
var img_style ={
width: 130,
borderRadius: 75
};
return(
<div style={user_photo}>
<img style={img_style} src={this.props.source}/>
</div>
);
}
});
var Details = React.createClass({
render: function() {
var title = {
color: "#999",
fontSize: 18,
margin: 0
};
var detail_value ={
color: "#2c2e31",
fontSize: 38,
margin: 5
}
return(
<div>
<p style={title}>My Name is</p>
<p style={detail_value}>{this.props.value}</p>
</div>
);
}
});
var Card = React.createClass({
render: function() {
var cardStyle = {
height: 380,
width: 650,
margin: 40,
backgroundColor: "#FFF",
textAlign: "center",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)"
};
return (
<div style={cardStyle}>
<AvatarHeader/>
<Avatar source ={this.props.data.picture.medium}/>
<Details value={this.props.data.name.first}/>
</div>
);
}
});module.exports = Card;
Step 6: Write the template for the CardList component. Every element in the list need to have a unique key, otherwise, there will be a warning in the console. Therefore, it is recommended to have a key for each element in the list. In this example, I have used email as the unique key and set the person object in props.data. As a result in the Avatar component, I have used the URL for the image as following in card.js
<Avatar source ={this.props.data.picture.medium}/>
This is the template for CardList component
var CardList = React.createClass({
... ... ... ...
... ... ... ...
render: function() {
return (
<div>
<h1>Persons!</h1>
// iterate the persons array and for each person render a card
{this.state.persons.map(function(person) {
return <Card key={person.email} data={person}/>;
})}
</div>
)
}
... ... ... ...
... ... ... ...
});
Step 7: Finally render CardList component in the container
ReactDOM.render(
<CardList source="http://api.randomuser.me/?results=5" />,
document.getElementById('app')
);
The full source code for index.js is as following
var React = require('react');
var ReactDOM = require('react-dom');
var Card = require('./components/card');
var axios = require('axios');var CardList = React.createClass({
getInitialState: function() {
return {
persons: []
}
},
componentDidMount: function() {
// Is there a React-y way to avoid rebinding `this`? fat arrow?
var th = this;
this.serverRequest =
axios.get(this.props.source)
.then(function(result) {
th.setState({
persons: result.data.results
});
})
},
componentWillUnmount: function() {
this.serverRequest.abort();
},
render: function() {
return (
<div>
<h1>Persons!</h1>
{/* Don't have an ID to use for the key, URL work ok? */}
{this.state.persons.map(function(person) {
return <Card key={person.email} data={person}/>;
})}
</div>
)
}
});ReactDOM.render(
<CardList source="http://api.randomuser.me/?results=5" />,
document.getElementById('app')
);
Step 7: Run the application using the command ‘npm run start’ and take a look at the browser. voilà!