React Flux Store: addChangeListener is not a function

Using React with Flux, you need to register a callback from your Component so that it can be called when the Store emits an event. For an ExampleComponent and ExampleStore, this might look like:

class ExampleComponent extends Component {

    constructor(props) {
        super(props);
    }

    componentWillMount(){
        ChatStore.on('change', this.handleUserNameChange);
    }
...
}

I’ve seen some examples where a helper function is declared in the Store that registers your Component as a listener, so the call from the Component to register with the Store might look like:

    componentWillMount(){
        ChatStore.registerChangeListener(this.handleUserNameChange);
    }

and in your ExampleStore you’ll declare registerChangeListener() (and similar to remove) like this:

addChangeListener(callback) {
    this.on('change', callback);
}

removeChangeListener(callback) {
    this.removeListener('change', callback);
}

All good so far, but here’s the issue I just ran into:

Uncaught TypeError: _ExampleStore2.default.addChangeListener is not a 
function
 at ExampleComponent.componentWillMount (ExampleComponent.jsx:19)
 at ReactCompositeComponent.js:348

Initially this is confusing, since it’s clear we did already declare addChangeListener, so why is this error saying it’s not a function?

The catch is in how we export the Store. The cause of my issue above was that I had exported it like this:

class ExampleStore extends EventEmitter {
..
}
export default ExampleStore;

This is how you would typically export a module but what we’re trying to do is treat the Store as a singleton instance. To do this the export should be:

export default new ExampleStore();

This approach is described in many Flux related articles (here’s an example), but it’s an easy mistake to miss.

Learning React and Flux – how many articles and references do you need before you can build a working example?

As an experienced developer of some 21 years, I have no problem in stating that learning React and Flux has a steep learning curve. It’s complex (until you understand it). If anyone else tries to tell you anything different I’d question if they know what they are talking about. They probably don’t. In fact they’re flat out lying if they say it’s anything but complex. The official Facebook documentation for Flux is terrible. I challenge anyone to build a working React app using Flux using the solely the Facebook Flux docs and no other sources and no other prior knowledge of how to build a React app using Flux. You won’t be able to. There’s too much information that’s missing. You might be able to create Actions and send them to your Dispatcher, but you won’t get to the point of having a working Flux event flow through View Controller, creating an Action, sending it to the Dispatcher, the Store, emitting events, and triggering a Component to update based on Store changes.

In learning Flux, I’d say I went through a substantial number of articles piecing together snippets of different approaches before I got to the point where I got the concept, and then many more to get to the point of actually having a working simplest case app up and running. In addition, I’ve also worked through a React and Flux tutorial on PluralSight, and part of part of another similar course on Udemy, and also watched numerous presentations on YouTube.

The trickiest part I found was that the docs and many articles talk about each of the individual parts of Flux, creating Actions, creating the Dispatcher, creating a Store, but what seems to be missing is the key part of how do you hook them all up to together, so the one way event flow works as it should. Miss out any one part and nothing happens. Your app just doesn’t work. Or you get obscure errors and you’ll have no idea what they’re talking about.

Here’s a summary of the best articles I’ve found that were the most useful:

http://blog.andrewray.me/flux-for-stupid-people/

https://discuss.reactjs.org/t/whats-the-best-flux-tutorial/51

https://scotch.io/tutorials/getting-to-know-flux-the-react-js-architecture

https://scotch.io/tutorials/creating-a-simple-shopping-cart-with-react-js-and-flux

https://brigade.engineering/what-is-the-flux-application-architecture-b57ebca85b9e#.8twu5mlke

https://medium.com/@nosherwan/flux-stores-with-es6-syntax-d2182552091e#.ozap6h8sb

  • parts of this article don’t work because you get at least the first error below, but it was useful in showing registering a Component to listen for events from a Store

 

Here’s a list of articles and posts for working round specific (weird) errors that I ran into:

Understanding binding ‘this’ to access setState() in ES6, to avoid this error:

Uncaught TypeError: this.setState is not a function

http://stackoverflow.com/questions/33381756/this-setstate-is-not-a-function
http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback
Why this.setState is undefined in React ES6 class? https://github.com/goatslacker/alt/issues/283

  • the magic answer from user troutowicz: “React components using ES6 classes no longer autobind this to non React methods. In your constructor, add:this.onChange = this.onChange.bind(this)"

What JavaScript voodoo is this!

Understanding this error when attempting to output state in the render() for a component: “Uncaught Error: Objects are not valid as a React child”

  • this error is particularly obscure. It turns out the ‘object’ in question was a property object where I was referencing part of the object parent properties to display in a render() using { } but the property I needed was nested further down. So
    { this.state.labelValue }

gave the error above, this referencing the property data correctly (in my case) like this worked:

  { this.state.labelValue.labelValue.value }

This was hinted by this post:
http://stackoverflow.com/questions/33117449/invariant-violation-objects-are-not-valid-as-a-react-child

I finally got to a working example, simplest case example, which you can see on my Github here. I feel like I’ve just earned my Flux badge 🙂