简体   繁体   中英

Why won't my react component re-render when componentShouldUpdate returns true?

I'm having trouble understanding how the lifecycle hooks work in my React application. I have an application in which I pass some props to my Pagination component in my render method like so:

<Pagination
  totalRecords={this.state.blogPosts.length}
  pageLimit={5}
  pageNeighbours={2}
  onPageChanged={() => {console.log('page changed');}}
/>

In the Pagination constructor, I print out the prop values.

const { totalRecords = null, pageLimit = 30, pageNeighbours = 0 } = props;
console.log('totalRecords=', totalRecords); 

It prints out 0.

Fair enough, I haven't fetched my blog posts yet. So in componentDidMount, I fetch the blog posts like so:

componentDidMount() {
  axios.get('/blogs').then(
    response => {
      if (response.data) {
        const entries = Object.entries(response.data);
        this.setState({ 
          blogPosts: entries.map(p => Object.assign({id: p[0]}, {...p[1]}))
            .sort((p1, p2) => p1.updatedAt > p2.updatedAt ? -1 : 1),
        });
      }
    },
    err => {
      console.log('err=', err);
    });
}

So now the blog posts are populated, but the Pagination component doesn't update (even though the blogs themselves seem to update).

This is where I need some guidance on how React lifecycle hooks work. Does the render method not re-run after the state has changed? I'm expecting the Pagination component to be re-render and this time have the totalRecords prop print out 3 (or some number higher than 0). Does the constructor only run once even if it re-renders?

So just in case I have to trigger a re-render, I ran this in the componentShouldUpdate() method:

shouldComponentUpdate(nextProps, nextState) {
  console.log('this.state.blogPosts.length=', this.state.blogPosts.length);
  console.log('nextState.blogPosts.length=', nextState.blogPosts.length);
  return this.state.blogPosts.length !== nextState.blogPosts.length;
}

Indeed, this.state.blogPosts.length shows 0 and nextState.blogPosts.length shows 3 . So they're different, and I'm expecting state to update with 3 blog posts. I return true if the lengths are different, which they are, so the component should update. Does that not mean re-render?

In any case, totalRecords is still 0. I even set a time interval in the Pagination component:

setInterval(() => {
  console.log('this.totalRecords =', this.totalRecords);
}, 5000);

Every five seconds it prints out 0... long after the blog posts have been fetched and added to the state.

Why does the Pagination component not update with the new value for totalRecords?

Maybe you forgot to use componentWillReceiveProps in Pagination component.

componentWillReceiveProps(nextProps) {
  this.setState({ totalRecords: nextProps.totalRecords })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM