Почему getDerivedStateFromProps вызывается после setState? - PullRequest
0 голосов
/ 25 июня 2018

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

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

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

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

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

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

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

Ответы [ 4 ]

0 голосов
/ 25 июля 2019

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

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
    })
}
0 голосов
/ 22 января 2019

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

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

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

0 голосов
/ 17 марта 2019

Способ 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
  }
}
0 голосов
/ 06 января 2019

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

this.state={flag:true}

In getderivedstatefromprops

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

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

...