从商店调用 api 并将数据绑定到 ReactJS/flux 中的组件状态

Call api from a store and bind data to component state in ReactJS/flux

使用 React-router-component,我已设置加载我的主页,其中包含一个名为 gigist 的组件,如下所示:

var React = require('react');
var AppStore =require('../../stores/app-store.js');
var GigsListItem = require('./giglistitem.js');
var StoreWatchMixin =require('../../mixins/StoreWatchMixin.js');

function getGigs()
{

    return {items:AppStore.getGigs()}
}

var GigsList= React.createClass({
  mixins:[new StoreWatchMixin(getGigs)],
  componentWillMount:function()
  {
     this.setState(getGigs());
     console.log(this.state);
  },
  componentDidMount:function()
  {
     this.setState(getGigs());
     console.log(this.state);
  },
    render:function()
    {
        console.log("rendered view");
        var liststyle={border:'1px solid black'};

        /*
        var items=this.state.items.map(function(item)
        {
            return <GigsListItem gig={item} />
        })  */
        return (

                <div className="row" style={liststyle}>
                {this.state.items}

                </div>
               )
    }
});

module.exports=GigsList;

我正在使用 npm reqwest 进行 ajax 调用,但问题是在完成 ajax 请求之前正在呈现视图并将其状态设置为未定义。 你可以从我的控制台日志中看到它

从控制台'1'是在设置组件giglist的初始状态,'3'是组件将挂载,'rendered view'是在渲染组件时,'2'是ajax请求

这清楚地表明在 ajax 调用之后数据没有被设置为组件状态。

我需要在收到响应后为组件设置状态。 我尝试使用 componentwillmount 和 componentdidmount 设置状态,但都没有解决我的问题。

这是我的商店代码:

var AppDispatcher = require('../dispatchers/app-dispatcher');
var AppConstants = require('../constants/app-constants');
var reqwest = require('reqwest');
var merge = require('react/lib/merge');
var EventEmitter = require('events').EventEmitter;

var CHANGE_EVENT = "change";

var _gigs = [];

function getGigsList()
{

reqwest({url:'myapi',
type:'get',
success:function(resp)
{
  console.log(2);
  return resp.gigs;  
  //alert(JSON.stringify(_gigs));
}.bind(this)})  


}  



var _cartItems = [];


function _removeItem(index){
  _cartItems[index].inCart = false;
  _cartItems.splice(index, 1);
}

function _increaseItem(index){
  _cartItems[index].qty++;
}

function _decreaseItem(index){
  if(_cartItems[index].qty>1){
    _cartItems[index].qty--;
  }
  else {
    _removeItem(index);
  }
}


function _addItem(item){
  if(!item.inCart){
    item['qty'] = 1;
    item['inCart'] = true;
    _cartItems.push(item);
  }
  else {
    _cartItems.forEach(function(cartItem, i){
      if(cartItem.id===item.id){
        _increaseItem(i);
      }
    });
  }
}

function _CartTotals()
{
  var qty=0,total=0;
  _cartItems.forEach(function(cartItem)
    {
       qty+=cartItem.qty;
       total+=cartItem.cost * cartItem.qty;

    });
  return {'qty':qty,'total':total}
}


var AppStore = merge(EventEmitter.prototype, {
  emitChange:function(){
    this.emit(CHANGE_EVENT)
  },

  addChangeListener:function(callback){
    this.on(CHANGE_EVENT, callback)
  },

  removeChangeListener:function(callback){
    this.removeListener(CHANGE_EVENT, callback)
  },

  getCart:function(){
    return _cartItems
  },

  getGigs:function(){
    alert(JSON.stringify(getGigsList()));
    return getGigsList();
  },

  getCartTotals:function()
  {
    return _CartTotals();
  },

  dispatcherIndex:AppDispatcher.register(function(payload){
    var action = payload.action; // this is our action from handleViewAction
    switch(action.actionType){
      case AppConstants.ADD_ITEM:
        _addItem(payload.action.item);
        break;

      case AppConstants.REMOVE_ITEM:
        _removeItem(payload.action.index);
        break;

      case AppConstants.INCREASE_ITEM:
        _increaseItem(payload.action.index);
        break;

      case AppConstants.DECREASE_ITEM:
        _decreaseItem(payload.action.index);
        break;
    }
    AppStore.emitChange();

    return true;
  })
})

module.exports = AppStore;

有人能指出我在做什么吗wrong.I希望我提前clear.Thanks

您不能在异步代码中使用 return 语句,即在您的 ajax 调用的成功回调中。

相反,尝试检查商店中是否已经有演出,如果是,您 return 他们,如果商店中没有演出,您会请求获得一些并成功回调您将商店状态设置为新数据并发出一个更改,告诉您的组件再次尝试获取商店状态。

    function getGigsList()
    {
        if (_gigs.length > 0) { return _gigs; } //return immediately if data exists

        reqwest({url:'myapi',
        type:'get',
        success:function(resp)
        {
            console.log(2);
            _.gigs = resp.gigs;  
            this.emit(CHANGE_EVENT);
        }.bind(this)}) 

        return _gigs; //currently an empty array. this way you don't have to check for undefined in the component, you can just iterate over it directly
    }