Состояние не обновляется немедленно ReactJS

Я не могу понять, что я делаю неправильно здесь. У меня есть событие, которое запускает функцию для изменения состояния нескольких значений, чтобы я мог запустить вызов API; однако при первом запуске функции состояния не меняются. При втором запуске функции устанавливается изменение состояния по сравнению с предыдущим запуском. Что может быть причиной этой задержки?

Итак, как вы можете видеть ниже, handleFilterChange получает значения от события, и я могу убедиться, что значения получены правильно; однако, если я проверю значение состояния сразу после его установки, я увижу, что оно не определено. Когда событие наступает во второй раз; однако я вижу, что исходное изменение состояния теперь произошло, а второе - нет. Так почему setState должен вызываться дважды, чтобы действительно установить состояние?

var GridView = React.createClass({
  getInitialState: function() {
    window.addEventListener("scroll", this.handleScroll);
    return {
      data: [],
      page: 0,      //for pagination
      loadingFlag: false,
    };
    },

  getMainFeed: function() {

...

 }, //end function
 getFilteredItems: function() {
  ...

}, //end function
  componentWillMount: function() {

  },
  listenForFilterChange: function() {
    window.addEventListener("selectedFilterChange", this.handleFilterChange, false);
  },
  componentWillUnmount: function() {
    window.removeEventListener("selectedFilterChange", this.handleFilterChange, false);
  },
  handleFilterChange: function(filter) {
   //alert(filter.detail.filterType);
   //Convert Data for getFilteredItems
   //(EventType, Category, Buy, Inspiration) {
   switch (filter.detail.filterType) {
     //alert(filter.detail.filterType);
    case 'category':
      this.setState({
        itemCategory: filter.detail.filterSelected,
      });
      break;
    case 'event':
      this.setState({
        eventType: filter.detail.filterSelected,
      });
      break;
    case 'type':
      if (0){
        this.setState({
          filterBuy: 1,
          filterInspiration: 0,
        });
      }
      if (1){
        this.setState({
          filterBuy: 0,
          filterInspiration: 1,
        });
      }
      if (2){
        this.setState({
          filterBuy: 1,
          filterInspiration: 1,
        });
      }
      break;
    case 'trending':
      this.setState({
        itemCategory: filter.detail.filterSelected,
      });
      break;
   }

   this.getFilteredItems();
 },
  componentDidMount: function() {
    this.listenForFilterChange();
...
  },
  handleScroll:function(e){
...
  },
  componentDidUpdate: function() {
...
  },
  render: function() {
      return (
        <div id="feed-container-inner">
          <GridMain data={this.state.data} />
        </div>

      );
    }
  });

person Bill Walters    schedule 13.08.2015    source источник


Ответы (2)


setState является асинхронным, поэтому изменения не сразу отражаются в состоянии:

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

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

person David Hellsing    schedule 13.08.2015
comment
Спасибо, @David. Я не понимал этого, теперь это имеет гораздо больше смысла. - person Bill Walters; 13.08.2015

setState не нужно вызывать дважды. Читая ваш код, я не могу точно определить, что не так, но могу посоветовать следующее:

  1. Если вы хотите знать, что в нем происходит, запишите свое состояние в Console.log в функции render.
  2. Проверьте еще раз, что находится в вашем событии (какой случай срабатывает и действительно ли он срабатывает). 3. Проверьте, не переопределяет ли другая функция (другой setState) состояние, которое вы хотите установить в handlefilterChange.

Могу поспорить, что ваш фильтр не получает правильные значения, сначала получая undefined filter.detail.filterSelected, а затем еще один определенный... Проверьте, что находится в filter.detail.filterSelected, я вижу в комментарии, который вы только проверили для filter.detail.filterType

В любом случае, ваша проблема связана не с setState, а с вашими данными, я уверен.

Дайте мне знать, если это помогло

person François Richard    schedule 13.08.2015
comment
Франсуа, я уже сделал эти проверки, оказалось, проблема в том, что setState является асинхронным, поэтому я должен использовать функцию обратного вызова. В очередной раз благодарим за помощь. - person Bill Walters; 13.08.2015
comment
хорошо, console.log в рендере сработал бы, но ответ Билла Уолтерса объясняет причину и является более точным. - person François Richard; 13.08.2015