Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 652
Harkirat Saluja Avatar asked Feb 06 '23 17:02

Harkirat Saluja


2 Answers

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
}
like image 142
Mark Avatar answered Feb 09 '23 20:02

Mark


Also, if you're using Redux, make a check like this to avoid an infinite loop:

componentWillReceiveProps(newProps) {
    if (this.props.someValue === newProps.someValue) {
        this.props.fetchSomething(newProps.params.somethingName);
    }
}
like image 39
Vlady Veselinov Avatar answered Feb 09 '23 21:02

Vlady Veselinov