Mixin for reflux stores to enable them to have state
, setState()
, storeDidUpdate()
and getInitialState()
, similar to React components.
// myStore.js
var Reflux = require('reflux');
var StateMixin = require('reflux-state-mixin')(Reflux); //call this mixin like that
var Actions = require('./../actions/AnimalsActions');
var AnimalStore = (module.exports = Reflux.createStore({
mixins: [StateMixin],
listenables: Actions, //or any other way of listening...
getInitialState() {
return {
dogs: 5,
cats: 3,
};
},
onNewDogBorn: function () {
this.setState({ dogs: this.state.dogs + 1 });
//just like in a Component.
//this will `trigger()` this state, similar to `render()` in a Component
},
//you can use storeDidUpdate lifecycle in the store, which will get called with every change to the state
storeDidUpdate: function (prevState) {
if (this.state.dogs !== prevState.dogs) {
console.log('number of dogs has changed!');
}
},
}));
var AnimalStore = require('./AnimalStore.js');
var DogsComponent = React.createClass({
mixins: [Reflux.ListenerMixin],
getInitialState: function () {
return {
dogs: AnimalStore.state.dogs,
//Treat store.state as immutable data - same as you treat component.state -
//you could use it inside a component, but never change it's value - only with setState()
};
},
componentDidMount: function () {
this.listenTo(AnimalStore.dogs, this.updateDogs);
//this Component has no interest in `cats` or any other animal, so it listens to `dogs` changes only
},
updateDogs: function (dogs) {
this.setState({ dogs: dogs });
//now we have auto-synchronization with `dogs`, with no need for specific logic for that
},
render: function () {
return (
<div>
<p>We have {this.state.dogs} dogs</p>
</div>
);
},
});
var AnimalStore = require('./AnimalStore.js');
var PetsComponent = React.createClass({
mixins: [Reflux.ListenerMixin],
getInitialState: function () {
return {
dogs: AnimalStore.state.dogs,
cats: AnimalStore.state.cats,
};
},
componentDidMount: function () {
this.listenTo(AnimalStore, (state) => {
this.setState({
dogs: state.dogs,
cats: state.cats,
});
});
//this way the component can easily decide what parts of the store-state are interesting
},
render: function () {
return (
<div>
<p>We have {this.state.dogs + this.state.cats} pets</p>
</div>
);
},
});
var AnimalStore = require('./AnimalStore.js');
var StateMixin = require('reflux-state-mixin')(Reflux);
var PetsComponent = React.createClass({
mixins:[
StateMixin.connect(AnimalStore, 'dogs')
//OR
StateMixin.connect(AnimalStore) //now PetsComponent.state === AnimalStore.state
],
render: function () {
return (<div><p>We have {this.state.dogs} dogs</p></div>);
}
})
$ npm install reflux-state-mixin --save
GetInitialState()
in store should have all of the states from the beginning.
setState()
is checking to see if there is a difference between new state.key
from current state.key
. If not, this specific state.key
it's not triggering.
For any setState()
the entire store is triggering (regardless of changes), allowing any Component or other Store to listen to the entire Store's state.
This mixin is combination of two other mixins - triggerables-mixin, a really useful mixin for controlling the trigger of the stores. Also see this for details. And state-mixin
I thank @jehoshua02 and @jesstelford for their valuable code.