0

Using React-router-component, i have set to load my home page with a component called gigist which is as folows:

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;

I am making an ajax call using npm reqwest,but the problem is that the view is being rendered and setting its state to undefined before completion of ajax request. You can see it from my console log From the consoe '1' is at setting initial state for component giglist,'3' is component will mount,'rendered view' is while rendering component,'2' is for the ajax request

From the console '1' is at setting initial state for component giglist,'3' is component will mount,'rendered view' is while rendering component,'2' is for the ajax request

which clearly states that data is not being set to component state after the ajax call.

I need to set state for the component after i get response from it. I tried setting state with componentwillmount and componentdidmount but neither solve my issue.

here is my store code:

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;

can somebody point out where i am doing wrong.I hope i am clear.Thanks in advance

Nithish Reddy J
  • 155
  • 3
  • 16

1 Answers1

4

You cannot use return statements in asynchronous code, i.e, in the success callback of your ajax-call.

Instead, try to check if there are already gigs in the store, in which case you return them, and if there are no gigs in the store you do a request to get some and in the success callback you set the store state to the new data and emit a change that will tell your component to try to fetch the store state again.

    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
    }  
Markus-ipse
  • 7,196
  • 4
  • 29
  • 34
  • Thank You for your answer.It worked. I have a scenario where i need to pass search text to the same function and call api. The function is being called recursively.Can you tell me why the function is being called recuesively?Is there a way to stop calling it after once the data is fetched from api and set to component state? – Nithish Reddy J Mar 11 '15 at 09:03
  • Glad to be able to help :) I think it would probably be best open a new question with code examples, etc. That way it's easier to give an answer and can be more easily found by others with similar problems. – Markus-ipse Mar 11 '15 at 12:08