Harkirat Saluja Harkirat Saluja - 14 days ago 14
React JSX Question

How to reload a component in reacts on url parameter change?

I have the following route:-

ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={app}>
<IndexRoute component={home}/>
<Route path="/articles" component={articles} />
<Route path="/articles/topics/:featureName" component={filteredArticles} />
</Route>
</Router>
), document.getElementById('app'));


Now when i request for /articles/topics/topic1, the first 5 contents are fetched are using API call. When user reaches the bottom of the page again an API call is made where next 5 contents are fetched. This is working fine(Notice that the handlescroll function checks for the page bottom, which has few minor issues so commented that out for now.)

Now say I choose next topic from the list so the url changes, so my url changes to /articles/topics/topic2 , now i need the same thing as mentioned above and call apis for this topic.

Following is my current component code:-

import React from 'react';
import axios from 'axios';
import ArticleList from './ArticleList';
import Banner from './Banner';
import LeftNavBar from './LeftNavBar';
import RightNavbar from './RightNavbar';
import {url} from './Constants';


/*MERGE INTO ARTICLES ONCE SCROLL LOGIC IS FIXED*/
class FilteredArticles extends React.Component{

constructor(){
super();
{/* Adding global event listener,binding it to scroll event and adding it to handleScroll function */}
/*window.addEventListener("scroll", this._handleScroll.bind(this));*/
this.state ={
articles : [],
loadingFlag:false,
limit : 5,
offset :0,
subFeatureName:[],
flag: false
}
}


_getContent(){
let self=this;
axios.get(url+'/articles/filter/?filter=popular&category='+this.props.params.featureName+'&limit='+this.state.limit+'&offset='+this.state.offset)
.then(function(response){
/*Checking if limit has exceeded meta count, if it has stopped we dont call the APIS*/
if(self.state.limit >= response.data.meta.total_count){
self.setState({articles : self.state.articles.concat(response.data.results),
offset : self.state.limit,
limit: self.state.limit+self.state.offset,
subFeatureName: self.props.params.featureName,
loadingFlag: false}
)
}
else{
self.setState({articles : self.state.articles.concat(response.data.results),
offset : self.state.limit,
limit: self.state.limit+self.state.offset,
subFeatureName: self.props.params.featureName,
loadingFlag: true}
)
}
})
.catch(function(error){
console.log(error);
});
}



_handleScroll(){
/*Calling 5 more articles when someone scrolls down and reaches the page end
const windowHeight = window.innerHeight;
const scrollT = $(window).scrollTop();
if(windowHeight- scrollT < 200){
if(!this.state.loadingFlag){
this.setState({loadingFlag : true});
this._getContent();
}
}*/
}

componentDidMount(){
/*calling _getContent function to get first five articles on page load*/
console.log("got content");
this._getContent();
}

render(){
console.log("inside render");
return(
<div>
<Banner title="Article Page"/>
<div className="content-container">
<LeftNavBar/>
<div className ="feeds">
<div className="card">
{/* Sending hideSeeAll as prop to remove see all button on main article page*/}
<ArticleList articles={this.state.articles} hideSeeAll='true' keyword="Top Articles"/>
</div>
</div>
<RightNavbar/>
</div>
</div>
)
}
}

export default FilteredArticles;


So basically I am trying to understand that if I have a route like /articles/topics/:featureName and I call a page like /articles/topics/topic1 or /articles/topics/topic2, can the component be realoaded(I need to call different API are fetch content once again).

That is, for /articles/topics/topic1 the API called is

/api/v0/articles/filter/?filter=popular&category=topic1&limit=5&offset=0

and for /articles/topics/topic2 the API called is

/api/v0/articles/filter/?filter=popular&category=topic2&limit=5&offset=0

Is there any way to achieve this?

Answer

You shouldn't really be querying the API/updating the components state in this fashion but hey that's another question entirely. Maybe consider using a Flux approach.

Anyhow, you can use the componentWillReceiveProps(nextProps) life cycle method to receive the routers nextProps params and query your API again:

componentWillReceiveProps(nextProps) {
    this._getContent(nextProps.params.featureName);
}

_getContent(featureName) {
 ...query your API
}