@The_good_game

Как работает функция componentDidUpdate?

Я только изучаю React, и не могу понять поведение функции React. Допустим, у меня имеется 2 компонента: родительский и дочерний.

class App extends React.Component {
  constructor(props) {
    super(props);

    this.value = '';
  }
  render() {
    return (
      <div className="App">
  
        <input onChange={(e) => {
          this.value = e.target.value
        }}></input>
        <button onClick={() => {
          this.setState({value: this.value})
        }}>Send</button>
  
      {this.state && <Child newValue={this.state.value}/>}
      </div>
    );
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);

    this.value = null;
  }

  componentDidUpdate(prevProps, prevState) {
    console.log('prevState')
    console.log(prevState);
    console.log('this.state')
    console.log(this.state)
    if (prevState === this.state) {
      this.setState({value: this.props.newValue})
    }
  }

  render() {
    return (
      <div>
        Hello!
      </div>
    )
  }
}


При нажатии на button родительский компонент обновляет своё состояние и повторно рендерид дочерний компонент. Но я совершенно не понимаю, почему здесь для корректной работы выполняется условие (prevState === this.state), а не (prevState !== this.state). Выводы из консоли:

// я ввёл в поле инпут единицу и нажал два раза button
// так как в первый раз дочерний элемент только монтируется, 
// а обновляется только при втором нажатии
prevState
null
this.state
null
prevState
null
this.state
{value: "1"}

// эти выводы покажутся, если я введу 12 и нажму button
prevState  
{value: "1"}  // почему здесь выводится значение {value: "1"}, а не null? 
              // Ведь изменение состояния не было.
this.state
{value: "1"}
prevState
{value: "1"}
this.state
{value: "12"}
  • Вопрос задан
  • 123 просмотра
Решения вопроса 1
@slide13
frontend/web-developer
  1. Вы ввели "1", нажали кнопку: у родителя меняется состояние на {value: "1"}, Child обновляется первый раз
  2. componentDidUpdate не срабатывает при первом рендере, поэтому в Child просто выводится Hello!
  3. В инпуте все еще "1", вы нажали второй раз кнопку. Снова вызывается setState с {value: "1"}, но каждый вызов setState приводит к перерендеру компонента, поэтому после второго клика происходит обновление родителя и вслед за ним потомка
  4. На второй перерендер у Child срабатывает componentDidUpdate, и т.к. состояние в потомке не определено, т.е. по дефолту равно null, то срабатывает условие в if в componentDidUpdate
  5. Child обновляет свой state и записывает туда {value: "1"}, после снова обновляется, но т.к. теперь предыдущий state был равен null, а текущий {value: "1"}, то условие if в componentDidUpdate уже не выполняется
  6. Добавляете в инпуте цифру "2", нажимаете кнопку. Родитель меняет состояние на {value: "12"} и обновляется вместе с потомком
  7. И дальше ответ на ваш вопрос: у Child снова после обновления срабатывает componentDidUpdate. При этом предыдущее значение у него в state осталось то, что было записано в пункте 5 и текущее тоже равно этому же значению, т.е. в этом случае опять сработает if и в Child изменится состояние на {value: "12"}
  8. Child снова обновляется после изменения своего состояния, срабатывает componentDidUpdate, предыдущее значение состояния value выводит "1", а текущее уже "12" так что if снова не срабатывает


Надеюсь понятно написал ) Не понятно только зачем вам в Child нужно состояние, которое дублирует пропы, так делать не надо
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы