javascript - update - set title reactjs




React.js, имеющий состояние, основанное на другом состоянии (2)

Я сталкиваюсь с некоторыми проблемами с React.js и состояние не устанавливается сразу при вызове setState (). Я не уверен, есть ли лучшие способы приблизиться к этому, или это действительно недостаток React. У меня есть две переменные состояния, одна из которых основана на другой. (Скрипка оригинальной проблемы: http://jsfiddle.net/kb3gN/4415/ вы можете увидеть в журналах, что она не сразу устанавливается, когда вы нажимаете кнопку)

setAlarmTime: function(time) {
  this.setState({ alarmTime: time });
  this.checkAlarm();
},
checkAlarm: function() {
  this.setState({
    alarmSet: this.state.alarmTime > 0 && this.state.elapsedTime < this.state.alarmTime
  });
}, ...

При вызове setAlarmTime , поскольку this.state.alarmTime не обновляется немедленно, следующий вызов checkAlarm устанавливает alarmSet на основе предыдущего значения this.state.alarmTime и поэтому является неправильным.

Я решил это, переместив вызов checkAlarm в обратный вызов setState в setAlarmTime , но необходимость отслеживать, какое состояние на самом деле является «правильным», и пытаться вписать все в обратные вызовы, кажется нелепым:

setAlarmTime: function(time) {
  this.setState({ alarmTime: time }, this.checkAlarm);
}

Есть ли лучший способ сделать это? В моем коде есть еще несколько мест, которые я ссылаюсь на состояние, которое я только что установил, и теперь я не уверен, когда действительно смогу доверять этому состоянию!

Спасибо


Да, setState является асинхронным, поэтому this.state не будет обновляться немедленно. Вот модульные тесты для пакетной обработки, которые могут объяснить некоторые детали.

В приведенном выше примере alarmSet - это данные, вычисленные из состояний alarmTime и elapsedTime . Вообще говоря, вычисленные данные не должны храниться в состоянии объекта, а должны вычисляться по мере необходимости как часть метода рендеринга. Есть раздел Что не должно идти в штате? в нижней части документации по интерактивным и динамическим интерфейсам, в которой приведены примеры таких вещей, которые не должны переходить в состояние, и какие компоненты должны иметь состояние? В разделе объясняются некоторые причины, по которым это может быть хорошей идеей.


Как сказал Дуглас, в общем случае не стоит сохранять вычисленное состояние в this.state , а вместо этого пересчитывать его каждый раз в функции render компонента, поскольку состояние будет обновляться этой точкой.

Однако это не будет работать для меня, так как мой компонент фактически имеет свой собственный цикл обновления, который должен проверять и, возможно, обновлять свое состояние при каждом тике. Поскольку мы не можем рассчитывать, что this.state будет обновляться при каждом тике, я создал обходной путь, который оборачивает React.createClass и добавляет его собственное внутреннее отслеживание состояния. (Требуется jQuery для $ .extend) (Fiddle: jsfiddle.net/kb3gN/4448 )

var Utils = new function() {
  this.createClass = function(object) {
    return React.createClass(
      $.extend(
        object,
        {
          _state: object.getInitialState ? object.getInitialState() : {},
          _setState: function(newState) {
            $.extend(this._state, newState);
            this.setState(newState);
          }
        }
      )
    );
  }
}

Для любых компонентов, где требуется актуальное состояние вне функции рендеринга, просто замените вызов React.createClass на Utils.createClass .

Вам также придется изменить все вызовы this._setState с помощью this._setState а вызовы this._state с помощью this._state .

Последним последствием этого является то, что вы потеряете автоматически сгенерированное свойство displayName в вашем компоненте. Это связано с заменой трансформатора JSX

var anotherComponent = React.createClass({

с

var anotherComponent = React.createClass({displayName: 'anotherComponent' .

Чтобы обойти это, вам просто нужно вручную добавить свойство displayName к вашим объектам.

Надеюсь это поможет





reactjs