Как принудительно обновить дочерний компонент React: простой способ

kak prinuditelno obnovit dochernij komponent react prostoj sposob

Примечание: по состоянию на React 16, componentWillReceiveProps() является устаревшим, то есть если вы используете эту или более новую версию в своем проекте, это не является хорошим советом для вас.

В мире React не воспринимают принудительный повторный рендеринг. Вы должны позволить DOM позаботиться о себе, когда React заметит изменения state или props. Чтобы следовать этим шаблонам, нам иногда приходится делать вещи, которые кажутся немного бессмысленными. Рассмотрим следующий сценарий:

SPU87A7KxxBLyug8JI0ZKYNqZH84EGfvO78o
Глупый простой пример дочернего компонента, управляющего собственным состоянием

У нас есть два компонента – отец и ребенок. Родительское устройство совершает вызов API для получения user. С этого мы получаем такие вещи name, age, favorite color. Мы также получаем id из нашей базы данных. Мы передадим это нашему дочернему компоненту, который также будет совершать вызов API с идентификатором пользователя. Прекрасно – в наше приложение поступает много данных.

Скажем, мы храним список обуви в базе данных. Когда пользователь изменяет свои цветовые предпочтения, сервер записывает новые данные в список обуви пользователя. Прекрасно! Кроме того, мы не видим новый список обуви в нашем дочернем компоненте. Что дает?

Дополнительное примечание: Конечно, мы должны просто получить обувь от пользовательского вызова — это лишь упрощенное объяснение.

Основы повторного воспроизведения React

Короче говоря, React будет обновлять только изменившиеся части DOM. В этом случае props переходим к компоненту обуви ( userId) не изменились, поэтому ничего не изменится в нашем дочернем компоненте.

Настройка цвета пользователя будет обновлена, когда мы получим новую информацию от API — если предположить, что мы что-то делаем с ответом после обновления пользователя.

Но поскольку React не видит причин обновлять список обуви, он этого не сделает даже если на нашем сервере обувь теперь другая.

Начальный код

const UserShow extends Component {
  state = {
    user: {}
  }
  
  componentDidMount() {
    this.fetchUser().then(this.refreshUser)
  }
  
  setNewColor = color => {
    this.updateUser({color}).then(this.refreshUser)
  }
  
  refreshUser = res => this.setState({user: res.data.user})
  
  render() {
    const { user } = this.state;
    
    return (
      <div>
        User name: {user.name}
        Pick color: 
        <div>
          {colors.map(color => 
            <div className={color} 
                 onClick={() => this.setNewColor(color)} />)}
          )}
        </div>
        <ShoeList id={user.id} />
      </div>
    )
  }
}

Наши ShoeList это просто список обуви, который мы получим с сервера с идентификатором пользователя:

const ShoeList extends Component {
  state = {
    shoes: []
  }
  
  componentDidMount() {
    this.fetchShoes(this.props.id)
        .then(this.refreshShoeList)
  }

  refreshShoeList = res => this.setState({ shoes: res.data.shoes })
  
  render() {
    // some list of shoes
  }
}

Если мы хотим, чтобы компонент обуви захватил новый список обуви, нам нужно обновить атрибуты, которые мы ему присылаем. В противном случае он не нуждается в обновлении.

Фактически то, как это написано, ShoeList никогда не будет обновляться, поскольку мы не зависим от реквизитов для визуализации. Давайте поправим это.

Запуск дочернего компонента для повторного воспроизведения

Чтобы заставить дочерний компонент повторно отобразить — и сделать новый вызов API — нам нужно будет передать изменяющееся свойство, если изменится настройка цвета пользователя.

Для этого мы добавим метод в setNewColor:

[...]

setNewColor = color => {
  this.updateUser({color}).then(res => {
    this.refreshUser(res);
    this.refreshShoeList();
  })
}

refreshShoeList = () => 
  this.setState({refreshShoeList: !this.state.refreshShoeList})
  
[...]

<ShoeList id={user.id} refresh={refreshShoeList}

Это обычный переключатель, который мы можем переключать. Я сохранил все как можно проще, но при производстве мы хотели бы убедиться, что цвет, который мы устанавливаем, отличается от цвета, который мы имели раньше. Иначе обновлять будет нечего.

Теперь в ShoeList:

componentWillReceiveProps(props) {
  const { refresh, id } = this.props;
  if (props.refresh !== refresh) {
    this.fetchShoes(id)
      .then(this.refreshShoeList)
  }
}

Если вы пройдете только refreshShoeList а затем переключаться на основе этого логического значения, компонент будет просто обновляться навсегда и навсегда.

Нам нужно убедиться, что переключатель щелкнул лишь один раз — поэтому мы просто проверим, что поступающие реквизиты отличаются от реквизитов, которые мы имели раньше. Если они разные, мы сделаем новый вызов API, чтобы получить новый список обуви.

И бум — наш дочерний компонент вынужденно обновляться.

componentWillReceiveProps

Следует уделить еще одну минуту, чтобы просмотреть, что происходит в последней части кода. в componentWillReceiveProps у нас есть единственная возможность просматривать новые реквизиты, когда они поступают, и сравнивать их с предыдущими.

Здесь мы можем обнаружить изменения (как у refresh), а также мы можем проверить наличие новых пропов (обратите внимание, например, что refresh есть сначала undefined).

Этот метод React является очень мощным способом манипулирования и исследования props.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *