Почему getDerivedStateFromProps вызывается после setState?

React представил новый статический метод getDerivedStateFromProps(props, state), который вызывается перед каждым методом рендеринга, но почему? Позвонить ему после смены опоры имеет смысл для меня, но после setState это не так, может быть, я что-то упустил.

Я создавал компонент datePicker в соответствии с требованиями моей компании, в компоненте дата контролируется с опоры. У меня есть следующее состояние в компоненте.

selectedDate: number;
selectedMonth: number;
selectedYear: number;
currentMonth: number;
currentYear: number;
view: string;

selected представляет выбранную дату, которая получена из подпорки даты, а currentMonth и currentYear представляют месяц и год в текущем представлении календаря.

Если date из пропеллера изменяет selected*, currentMonth и currentYear должны быть изменены соответственно. Для этого я использую getDerivedStateFromProps, но, скажем, пользователь нажимает на название месяца, которое переключит представление календаря на месяц (вместо того, чтобы будет отображаться название месяца), функция обновляет currentMonth для этого с помощью setState, но date: реквизит тот же, что и раньше (содержащий предыдущий месяц), который должен, но вызывается getDerivedStateFromProps и currentMonth снова такой же, как и раньше, вместо изменения.

Хорошо, я создал дополнительную переменную в state, чтобы отслеживать, вызван ли getDerivedStateFromProps из-за setState, но я не думаю, что это правильный путь.

Либо я делаю что-то не так, либо что-то пропускаю, либо getDerivedStateFromProps не следует вызывать после setState. Вероятно, я делаю что-то не так.

Ответ 1

Я сделал что-то вроде этого

constructor(props) {
    super(props);
    this.state = {
        expanded: props.expanded,
        ownUpdate: false
    }
}

static getDerivedStateFromProps(props, state) {
    if (state.ownUpdate) {
        return {
            expanded: state.expanded,
            ownUpdate: false
        };
    } else if (props.expanded !== state.expanded) {
        return {
            expanded: props.expanded
        };
    }
    return null;
}

toggle() {
    this.props.onAftePress(this.state.expanded, this.props.index);
    this.setState({
        expanded: !this.state.expanded,
        ownUpdate: true
    })
}

Ответ 2

Я также получил эту проблему. Поэтому я установил другую переменную для проверки того, что реквизит получен впервые.

this.state={flag:true}

В getderivedstateromprops

static getderivedstatefromprops(props, state){
   if(props.<*propName*> && flag){
      return({ props.<*propName*>, flag:false})
   }
}

если вы хотите использовать несколько значений реквизита, вам необходимо соответственно установить операторы if (или любую другую логику).

Ответ 3

Хук getDerivedStateFromProps работает при получении новых реквизитов, setState и forceUpdate.

В версии 16.3 React не влияет на getDerivedStateFromProps всякий раз, когда используется setState. Но они улучшили его в версии, начиная с 16.4, поэтому всякий раз, когда вызывается setState, подключается getDerivedStateFromProps.

Вот извлеченное изображение из Реагирует на диаграмму жизненного цикла:

16.3

enter image description here

^ 16,4

enter image description here


Итак, вам решать, когда подключить getDerivedStateFromProps, правильно проверяя реквизиты и состояния. Вот пример:

static getDerivedStateFromProps (props, state) {
  // check your condition when it should run?
  if(props.currentMonth != state.currentMonth) {
    return {
      currentMonth: state.currentMonth
    }
  }
  // otherwise, don't do anything
  else {
   return null
  }
}

Ответ 4

у вас есть ответ на ваш вопрос сам. msgstr "который вызывается перед каждым методом рендеринга". Всякий раз, когда вы делаете setState метод render.

Я бы посоветовал вам поднять переменные состояния currentMonth и currentYear в родительский компонент и передать их как prop вместе с другими тремя. Вы также можете передать обработчик изменений как реквизит и вызвать его от ребенка.

при начальном render - currentMonth и currentYear могут иметь значение null, чтобы вы могли иметь логику для отображения материала по умолчанию. Когда кто-то changeHandler название месяца, вы можете вызвать changeHandler из parent, который пропустит новую реквизит. Теперь в getderivedstatefromprops вас больше нет currentMonth и currentYear как 'null', поэтому вы знаете, что месяц изменился.