Почему мой реагирующий компонент не выполняет повторную визуализацию, когда componentShouldUpdate возвращает true?

Мне сложно понять, как работают хуки жизненного цикла в моем приложении React. У меня есть приложение, в котором я передаю некоторые реквизиты компоненту разбиения на страницы в моем методе рендеринга, например:

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

В конструкторе разбиения на страницы я распечатываю значения свойств.

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

Он выводит 0.

Честно говоря, я еще не получил свои сообщения в блоге. Итак, в componentDidMount я получаю сообщения в блоге следующим образом:

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);
    });
}

Итак, теперь сообщения в блогах заполнены, но компонент разбиения на страницы не обновляется (хотя сами блоги, кажется, обновляются).

Здесь мне нужно руководство о том, как работают хуки жизненного цикла React. Не запускается ли метод рендеринга повторно после изменения состояния? Я ожидаю, что компонент Pagination будет повторно отрисован, и на этот раз свойство totalRecords распечатает 3 (или какое-то число больше 0). Конструктор запускается только один раз, даже если он перерисовывается?

Так что на случай, если мне нужно запустить повторный рендеринг, я запустил это в методе componentShouldUpdate():

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;
}

Действительно, this.state.blogPosts.length показывает 0, а nextState.blogPosts.length показывает 3. Итак, они разные, и я ожидаю, что состояние обновится с 3 сообщениями в блоге. Я возвращаю true, если длины отличаются, а они есть, поэтому компонент должен обновиться. Разве это не означает повторный рендеринг?

В любом случае totalRecords все равно 0. Я даже установил временной интервал в компоненте Pagination:

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

Каждые пять секунд он печатает 0 ... долгое время после того, как сообщения блога были извлечены и добавлены в состояние.

Почему компонент Pagination не обновляется с новым значением totalRecords?


person gib65    schedule 10.11.2020    source источник
comment
Может быть более полезным опубликовать минимальный, полный и воспроизводимый пример кода компонента. С помощью всего нескольких фрагментов трудно понять, что еще может делать ваш компонент, каким может быть ваше начальное состояние или как ваш Pagination компонент обрабатывает обновления свойств. Можете ли вы включить как Pagination код компонента , так и код компонента, который отображает Pagination? Что this.totalRecords в интервале? Неужели это this.props.totalRecords?   -  person Drew Reese    schedule 10.11.2020
comment
кажется, что this.totalRecords, вероятно, опечатка и должно быть this.state.totalRecords?   -  person andersryanc    schedule 10.11.2020
comment
@DrewReese согласился, нужна дополнительная информация. мне кажется, что внутри компонента <Pagination /> может быть что-то, из-за чего он не перерисовывается.   -  person andersryanc    schedule 10.11.2020
comment
Извините за недостаточную детализацию. Ответ Десмонда Хью сработал в моей ситуации, поэтому нет необходимости следить за этим.   -  person gib65    schedule 11.11.2020


Ответы (1)


Возможно, вы забыли использовать componentWillReceiveProps в Pagination компоненте.

componentWillReceiveProps(nextProps) {
  this.setState({ totalRecords: nextProps.totalRecords })
}
person Desmond Hiew    schedule 10.11.2020
comment
Это помогло, Десмонд. Я предполагаю, что это означает, что конструкторы компонентов не вызываются повторно каждый раз при рендеринге компонента. Я поместил console.log в конструктор, чтобы быть уверенным, и действительно, он вызывается только один раз, хотя сейчас totalRecords обновляется благодаря componentWillReceiveProps (). - person gib65; 11.11.2020