Last Finishes
Our app looks great now, but there some more things we could improve:
For example- when the user has not performed any search yet it is good to display no items yet message instead of "some item".
Lets modify Results List component accordingly:
// Results List
var ResultsList = React.createClass({
render: function() {
var createItem = function(item, idx) {
return {item.text} ;
};
var list;
if(this.props.results && this.props.results.length) {
list = this.props.results.map(createItem);
}else{ // <--- no search results came from server
list = 'no items yet';
}
return {list}
;
}
});
Displaying loading animation
It is good practice to display animation when request sent but results hasn't come back yet.
That way user will notified that his actions were noticed and the the server working to fulfill his request.
That means we should pass another property from SearchPage to ResultsList component
- loading which will "tell" the results component when request started and when it finished (e.g. when to show loading animation):
loadResults: function(query){
if(query==''){
this.setState({
loading: false,
results:[]
});
return;
}
this.setState({loading:true}); // <--- the request started so animation must be visible
var results = [];
var url = "https://api.github.com/search/repositories?q="+query+"+language:typescript&sort=stars&order=desc";
$.get(url)
.then(function (result) {
if(result.items.length!==0){
results =result.items.map(item => {
return {text: item.name}
}).slice(0,5);
}else{
results = []
}
this.setState({loading: false, results:results});
}.bind(this));//<-- important to bind this for use "setState"
}
...
...
...
render: function() {
return (
<div >
<SearchBar onTextChange={this.handleSearchTextChange}/ >
<ResultsList results={this.state.results} loading={this.state.loading}/ > //<---passing loading property to ResultsList component
</div >
);
}
Animation
i will add to project the CSS code i took from this awesome project so it will display spinner animation:
.loader {
margin: 20px auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid rgba(6,178,103, 0.2);
border-right: 1.1em solid rgba(6,178,103, 0.2);
border-bottom: 1.1em solid rgba(6,178,103, 0.2);
border-left: 1.1em solid #06b267;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
.loader,
.loader:after {
border-radius: 50%;
width: 5em;
height: 5em;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
After adding the animation css, we need to modify the
ResultsList component code so it will be able to display the animation:
// Results List
var ResultsList = React.createClass({
render: function() {
var createItem = function(item, idx) {
return <li key={idx}>{item.text}</li>;
};
var list;
if(this.props.results && this.props.results.length && !this.props.loading) {
list = this.props.results.map(createItem);
} else if(this.props.results.length==0 && !this.props.loading){
list = 'no items yet';
} else if(this.props.loading) {
list = <div className="loader">Loading... </div>;
}
return <ul className="results">{list} </ul>;
}
});
Now the animation is displayed
the code on plnkr
Hope you have fun reading