I'm new to react and flux and I am having a hard time trying to figure out how to load data from a server. I am able to load the same data from a local file with no issues.
So first up I have this controller view (controller-view.js) that passes down initial state to a view (view.js)
controller-view.js
var viewBill = React.createClass({
getInitialState: function(){
return {
bill: BillStore.getAllBill()
};
},
render: function(){
return (
<div>
<SubscriptionDetails subscription={this.state.bill.statement} />
</div>
);
}
});
module.exports = viewBill;
view.js
var subscriptionsList = React.createClass({
propTypes: {
subscription: React.PropTypes.array.isRequired
},
render: function(){
return (
<div >
<h1>Statement</h1>
From: {this.props.subscription.period.from} - To {this.props.subscription.period.to} <br />
Due: {this.props.subscription.due}<br />
Issued:{this.props.subscription.generated}
</div>
);
}
});
module.exports = subscriptionsList;
I have an actions file that loads the INITAL data for my app. So this is data that is not called by as user action, but called from getInitialState in the controller view
InitialActions.js
var InitialiseActions = {
initApp: function(){
Dispatcher.dispatch({
actionType: ActionTypes.INITIALISE,
initialData: {
bill: BillApi.getBillLocal() // I switch to getBillServer for date from server
}
});
}
};
module.exports = InitialiseActions;
And then my data API looks like this
api.js
var BillApi = {
getBillLocal: function() {
return billed;
},
getBillServer: function() {
return $.getJSON('https://theurl.com/stuff.json').then(function(data) {
return data;
});
}
};
module.exports = BillApi;
And this is the store store.js
var _bill = [];
var BillStore = assign({}, EventEmitter.prototype, {
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
emitChange: function() {
this.emit(CHANGE_EVENT);
},
getAllBill: function() {
return _bill;
}
});
Dispatcher.register(function(action){
switch(action.actionType){
case ActionTypes.INITIALISE:
_bill = action.initialData.bill;
BillStore.emitChange();
break;
default:
// do nothing
}
});
module.exports = BillStore;
So as I mentioned earlier, when I load data locally using BillApi.getBillLocal() in actions everything works fine. But when I change to BillApi.getBillServer() I get the followind errors in the console...
Warning: Failed propType: Required prop `subscription` was not specified in `subscriptionsList`. Check the render method of `viewBill`.
Uncaught TypeError: Cannot read property 'period' of undefined
I also added a console.log(data) to BillApi.getBillServer() and I can see that the data is returned from the server. But it is displayed AFTER I get the warnings in the console which I believe may be the issue. Can anyone offer some advice or help me to fix it? Sorry for such a long post.
UPDATE
I made some changes to the api.js file (check here for change and DOM errors plnkr.co/edit/HoXszori3HUAwUOHzPLG ) as it was suggested that the issue is due to how I handle the promise. But it still seems to be the same issue as you can see in the DOM errors.
subscriptionsList
? It is looking forthis.props.subscriptions
and it is non-existent so you getCannot read property 'period' of undefined
. My guess is you also have some type of race condition as well. Flux is asynchronous by nature... – Lumbricalis_bill
a default object such asvar _bill = { subscriptions: [] }
so when you dogetInitialState
you just get thebill
viastore.getAllBill()
. then when the component mounts, the data is fetched, and the store will emit the change and update your state – Lumbricalis