0

I am currently trying out the FLUX design pattern and I have stumpled upon an issue. In this project I am also using ReactJS to go with it. It is working fine to a point where it is almost done, but screws up. So I am starting the function(s) with a button that I render, when clicked it fires the chain of functions.

    render: function(){
     return (
        <div><button onClick={this.waiting}>Hello</button>
            {this.state.results}
        </div>
    )
   }

you can now see that when this button is clicked, it fires a function called waiting() which contains the following

waiting: function() {
    actions.trending();
    return this.state.results;
},

So it fires the function and the following happens

    var actions = {
    trending: function(){
        api.trending()
        .then(function(result){
                dispatcher.dispatch({
                    actionType: actionConstants.TRENDING_RESULT,
                    results: result
                });
        }, function(error){
            console.log(error);
            dispatcher.dispatch({
                actionType: actionConstants.ERROR,
                error: error
            });
        });
    }   
};

which is all working fine, I am getting my data and I am happy so far, problem is what happens next, when the dispatcher dispatches the actionType along with the data, this goes into the store I have. In my store-file I am then registering the payload(action).

    dispatcher.register(function(action){
    switch (action.actionType) {
        case actionConstants.TRENDING_RESULT:
            console.log(action.results); <- I can actually see my data
            results = action.results;
            resultErrors = null;
            SearchStore.emit(actionConstants.TRENDING_RESULT); <- Error
            break;
        case actionConstants.ERROR:
            results = null;
            resultErrors = action.error;
            console.log(resultErrors);
            SearchStore.emit(actionsConstants.ERROR);
            break;
    }
});

So at this point I can see my data in the console.log but I am getting an error at the emit function that sounds as following

Uncaught (in promise) TypeError: this._events[evt].push

for my store functions I use the following

    var SearchStore = {
    getTrending: function() {
        return JSON.stringify(results); 
    },
    getError: function() {
        return resultErrors;
    },
    emit: function(event) {
        eventEmitter.on(event);
    },
    on: function(event, callback) {
        eventEmitter.on(event, callback);
    },
    removeListener: function(event, callback) {
        eventEmitter.removeListener(event, callback);
    }
};

and finally to pick up on any emits I call my on function in ComponentDidMount that looks like this

    componentDidMount: function(){
    SearchStore.on(actionConstants.TRENDING_RESULT, this.loadResults());
    SearchStore.on(actionConstants.ERROR, this.showError());
},

componentWillUnmount: function(){
    SearchStore.removeListener(actionConstants.TRENDING_RESULT, this.loadResults());
    SearchStore.removeListener(actionConstants.ERROR, this.showError());
},

For the Dispatcher I am using Facebooks FLUX dispatcher and for the emitter I am using eventemitter3. Everything is going smoothly up until I try to emit TRENDING_RESULT and and the payload with it. I am terribly sorry about the length of this question, but I wanted to be as thorough as I possibly could for your understanding.

DCBN
  • 65
  • 2
  • 8

2 Answers2

1

The event emitter should call emit function not the on function. So it should be something like:

 var SearchStore = {
    getTrending: function() {
        return JSON.stringify(results); 
    },
    getError: function() {
        return resultErrors;
    },
    emit: function(event) {
        eventEmitter.emit(event); // HERE!!
    },
    on: function(event, callback) {
        eventEmitter.on(event, callback);
    },
    removeListener: function(event, callback) {
        eventEmitter.removeListener(event, callback);
    }
};
ema
  • 5,668
  • 1
  • 25
  • 31
  • Thank you sir, I was following an example at got an error. I never noticed that he also used eventEmitter.emit(event) inside his emit function however I eliminated that function and restructered my code. I will post my solution below. Thank you for your time! – DCBN Dec 28 '15 at 15:05
  • You are welcome. If you can please set the question as "answered" it's helpful for others. – ema Dec 29 '15 at 12:58
0

My solution was as following:

'use strict';

var dispatcher = require('../dispatcher/dispatcher');
var EventEmitter = require('events').EventEmitter;
var ObjectAssign = require('object-assign');
var actionConstants = require('../constants/actionConstants');

var _store = {
    list: [],
    error: [],
    genres: [],
    playlists: []
}
var resultErrors = null;
var CHANGE_EVENT = 'change';

var SearchStore = ObjectAssign( {}, EventEmitter.prototype, {
    getTrending: function() {
        return _store;
    },
    getError: function() {
        return _store;
    },
    addChangeListener: function(callback){
        this.on(CHANGE_EVENT, callback);
    },
    removeListener: function(callback) {
        this.removeListener(CHANGE_EVENT, callback);
    },
    getGenres: function() {
        return _store;
    },
    getPlaylists: function() {
        return _store;
    }
});

dispatcher.register(function(action){
    switch (action.actionType) {
    case actionConstants.TRENDING_RESULT:
        action.results.map(function(item){
            _store.list.push(item);
        });
        resultErrors = null;
        SearchStore.emit(CHANGE_EVENT);
        break;
    case actionConstants.SEARCH_RESULT:
        _store.list = [];
        console.log(_store.list);
        action.results.map(function(item){
            _store.list.push(item);
        });
        resultErrors = null;
        SearchStore.emit(CHANGE_EVENT);
        break;
    case actionConstants.ERROR:
        results = null;
        _store.error.push(action.error);
        SearchStore.emit(CHANGE_EVENT);
        break;
    case actionConstants.ADD_GENRE:
        _store.genres.push(action.index);
        SearchStore.emit(CHANGE_EVENT);
        break;
    case actionConstants.REMOVE_GENRE:
        _store.genres = _store.genres.filter(function(index){
            return index !== action.index;
        });
        console.log(_store.genres);
        SearchStore.emit(CHANGE_EVENT);
        break;
    case actionConstants.SAVE_PLAYLIST:
        var playlists = {
            "name": action.index,
            "items": {}
        }
        ;
        _store.playlists.push(playlists);
        SearchStore.emit(CHANGE_EVENT);
        break;
    default:
    }
});

So I eliminated my my "emit" and "on" function all together and made a addChangeListener. so I emit straight from my switch cases and since "emit" is a already a function I don't need to create a function for a "emit" function. I just use my listener to pick up on CHANGE_EVENT and then it will run a callback function. Example:

componentDidMount: function(){
    SearchStore.addChangeListener(this.loadPlaylists);
},

componentWillUnmount: function(){
    SearchStore.removeListener(this.loadPlaylists);
},

As it is now it works perfectly, I understand that if I had just looked thoroughly through my code I could have been saved the trouble but the more you learn right? Anyways thanks for your time yet again.

DCBN
  • 65
  • 2
  • 8