From 2 weeks ago I'm facing a problem in my React/Flux app. It's done in ES6 and using webpack and babel.
It actually doesn't go inside the _onChange method ones the store emit the change event. So the component itself doesn't render again with the modified state.
Here you can take a look to my component:
import React from 'react';
import Item from 'components/item/item';
import Actions from './item-list.actions';
import Store from './item-list.store';
const StoreInstance = new Store();
class ItemList extends React.Component {
constructor(props) {
super(props);
this._onChange = this._onChange.bind(this);
this.state = this.getItemListState();
}
componentWillMount() {
StoreInstance.addChangeListener(this._onChange);
Actions.requestFlats(Actions.setFlats);
}
componentWillUnmount() {
StoreInstance.removeChangeListener(this._onChange);
}
_onChange() {
this.setState(this.getItemListState);
}
getItemListState() {
return {
flats: StoreInstance.getFlats()
}
}
render() {
return(
<ul className="item__list">{
this.state.flats.map((flat, index) => {
<li className="col-xs-12 col-sm-12 col-md-6 col-lg-6">
<Item key={index} flat={flat}></Item>
</li>
})
}</ul>
);
}
}
export default ItemList;
My actions:
import AppDispatcher from 'services/dispacher/dispacher';
import Constants from './item-list.constants';
let ItemListActions = {
getFlats: () => {
AppDispatcher.handleAction({
type: Constants.GET_FLATS,
data: {}
});
},
setFlats: (flats) => {
AppDispatcher.handleAction({
type: Constants.SET_FLATS,
data: {
flats
}
});
},
requestFlats: (callback) => {
AppDispatcher.handleAction({
type: Constants.REQUEST_FLATS,
data: {
callback
}
});
}
};
export default ItemListActions;
And store:
import AppDispatcher from 'services/dispacher/dispacher';
import AppStore from 'services/store/store';
import Api from './item-list.api';
import Constants from './item-list.constants';
class ItemListStore extends AppStore {
constructor() {
super();
this.flats = [];
}
requestFlats(callback) {
Api.getFlats(callback);
}
getFlats() {
return this.flats;
}
setFlats(flats) {
this.flats = flats;
}
}
const ItemListStoreInstance = new ItemListStore();
AppDispatcher.register((payload) => {
let action = payload.action;
switch (action.type) {
case Constants.GET_FLATS:
ItemListStoreInstance.getFlats(action.data);
break;
case Constants.SET_FLATS:
ItemListStoreInstance.setFlats(action.data.flats);
break;
case Constants.REQUEST_FLATS:
ItemListStoreInstance.requestFlats(action.data.callback);
break;
default:
return true;
}
ItemListStoreInstance.emitChange();
});
export default ItemListStore;
which extends of AppStore
import EventEmitter from 'events';
const CHANGE_EVENT = 'change';
class Store extends EventEmitter {
constructor() {
super();
}
emitChange() {
this.emit(CHANGE_EVENT);
}
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
}
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
}
Store.dispatchToken = null;
export default Store;
I have check this code many times and looking at examples over the whole Internet and I got no success.
I's supposed that when I do:
StoreInstance.addChangeListener(this._onChange);
the store will listen for my change event, but looks like it doesn't. When I got the new data from the API, I execute setFlats and _onChange is not executed, so no changes on the UI are shown.
Do you see any issue in this code? Anything that could help me to solve it?
Thanks in advance.
The problem was actually in the store which was returning the ItemListStore instead of an instance of ItemListStore and then in the component I was having another instance, that's why it wasn't communication with each other.
Here is the fixed code for the ItemListStore:
import AppDispatcher from 'services/dispacher/dispacher';
import AppStore from 'services/store/store';
import Api from './item-list.api';
import Constants from './item-list.constants';
class ItemListStore extends AppStore {
constructor() {
super();
this.flats = [];
}
requestFlats(callback) {
Api.getFlats(callback);
}
getFlats() {
return this.flats;
}
setFlats(flats) {
this.flats = flats;
}
}
const ItemListStoreInstance = new ItemListStore();
AppDispatcher.register((payload) => {
let action = payload.action;
switch (action.type) {
case Constants.GET_FLATS:
ItemListStoreInstance.getFlats(action.data);
break;
case Constants.SET_FLATS:
ItemListStoreInstance.setFlats(action.data.flats);
break;
case Constants.REQUEST_FLATS:
ItemListStoreInstance.requestFlats(action.data.callback);
break;
default:
return true;
}
ItemListStoreInstance.emitChange();
});
export default ItemListStoreInstance;