React + Flux: Getting initial state into a store React + Flux: Getting initial state into a store reactjs reactjs

React + Flux: Getting initial state into a store


It feels wrong to me that you are using getInitialState() to change the state of your store. You should at least be doing that in componentWillMount.

I would trigger an action in componentWillMount and have the store handler update the internal state of the store (this should always be the case in flux). Then your component's change handler for the store can consume whatever data that you are currently calling your "initial state"


Reflux.listenTo does this when you provide a third argument and Reflux.connect mixin factory (that uses Reflux.listenTo under the hood) handles this for you automatically. Here is an example:

var Actions = Reflux.createActions({"doIt"});var Store = Reflux.createStore({    listenables: [Actions],    init: function() {        this.state = "I like to";    },    onDoIt: function() {        this.state = "Do it";        this.trigger(this.state);    },    getInitialState: function() {        return this.state;    }});var DoItButton = React.createClass({    mixins: [Reflux.connect(Store, "label")],    onClick: function() {        Actions.doIt();    },    render: function() {        return (<div onClick={this.onClick}>{this.state.label}</div>);    }});


Like other posters have said, the best thing to do is to trigger an action in componentWillMount. In ES6, this is usually done with a constructor.

Below is an example on how to do this with ES6:

(note that AuthorActions.initAuthors() is dependent on implementation, this is just an example. This could get initial state from database. Most importantly though, this action should dispatch the payload with the initial state to the dispatcher)

var _authors = [];var AuthorStoreInstance;class AuthorStore extends EventEmitter {    constructor(props) {        super(props);    }    init() {        AuthorActions.initAuthors();        this.emitChange();    }    addChangeListener(cb) {        this.on(CHANGE_EVENT, cb);    }    removeChangeListener(cb) {        this.removeListener(CHANGE_EVENT, cb);    }    emitChange() {        this.emit(CHANGE_EVENT);    }    getAllAuthors() {        return _authors;    }    addAuthor(author) {        _authors.push(author);        this.emitChange();    }    setAuthors(authors) {        _authors = authors;    }};AuthorStoreInstance = new AuthorStore();Dispatcher.register((action) => {    switch(action.actionType) {        case ActionTypes.CREATE_AUTHOR:            AuthorStoreInstance.addAuthor(action.author);            break;        case ActionTypes.INITIALIZE:            AuthorStoreInstance.setAuthors(action.initialData.authors);            break;        default:            //do nothing    }});AuthorStoreInstance.init();export default AuthorStoreInstance;

Notice how the init function is not a part of the constructor. This is because when the authorStore is constructed, the callback for the AuthorActions.initAuthors has not been registered with the dispatcher.

Initialization should happen after callbacks have been registered with the dispatcher.

edit: For clarity, initAuthors could look something like this:

initAuthors() {    var authors = AuthorAPI.getAllAuthors();    Dispatcher.dispatch({        actionType: ActionTypes.INITIALIZE,        initialData: {            authors: authors        }    });}