Search code examples
javascriptreactjsreactjs-fluxalt.js

ReactJS - store.getState() undefined


I am getting data from an external api using the altjs implementation of Flux. The api call works fine from the action, is returned back to the store, and then the onChange() function is triggered in my component. I try to set the state from the current state of the store :

import React, { Component, PropTypes } from 'react';
import AppStore from '../../stores/AppStore';
import AppActions from '../../actions/AppActions';

const title = 'Contact Us';


class ContactPage extends Component {

    constructor(props) {
        super(props);
        this.state = AppStore.getState();
    }

  static contextTypes = {
    onSetTitle: PropTypes.func.isRequired,
  };

  componentWillMount() {
    AppActions.getData();
    this.context.onSetTitle(title);
    AppStore.listen(this.onChange)
}

componentWillUnmount() {
    AppStore.unlisten(this.onChange)
}

onChange() {
    this.state = AppStore.getState();
}

  render() {
    return (
      <div className={s.root}>
        <div className={s.container}>
          <h1>{title}</h1>
          <span>{this.state.data.id}</span>
        </div>
      </div>
    );
}

}

export default ContactPage;

I am getting the error "Cannot set property 'state' of undefined"

My store looks like this :

import alt from '../alt';
import AppActions from '../actions/AppActions';

class AppStore {
    constructor() {
        this.bindActions(AppActions);
        this.loading = false;
        this.data = {};
        this.error = null
    }

    onGetDataSuccess(data) {
        this.data = data;
    }
}

export default alt.createStore(AppStore, 'AppStore');

this.state = AppStore.getState() doesn't throw any errors in the constructor. It is just being thrown in the onChange() function. What is the proper way I should be setting the state here?


Solution

  • When you use ES6 classes you need to bind all the callbacks explicitly since there is no autobind. It may be confusing since when you use React.createClass, react will automatically bind all the callbacks into the component and thats why you could just pass this.onChange as a callback.

    Eg.

    componentWillMount() {
      ...
      AppStore.listen(this.onChange.bind(this));
    }