Reputation: 7648
I have made an attempt to hook the store into react component defined via React.createClass. I have achieved a global state but a lot of re-factoring needs to be done.
I will share the relevant code and proceed with questions thereafter.
Actions
var Reflux = require('reflux');
module.exports = Reflux.createActions(['markAllRead']);
Store
var Reflux = require('reflux');
var StoreActions = require('../actions/storeActions/notifications');
var React = require('react');
module.exports = Reflux.createStore({
init: function(){
this.listen(StoreActions.markAllRead, this.markAllRead);
this.state = {
unreadCount: 5
};
},
markAllRead(count){
this.state = {
unreadCount: 1
};
this.trigger(this.state);
}
});
Header Component
var notificationsStore = require('../stores/notifications');
getInitialState: function() {
// this.state = {}; // our store will add its own state to the component's
// this.store = notificationsStore; // <- just assign the store class itself
return {
notificationsData: this.props.notificationsData,
state: {},
store: notificationsStore
};
},
Inside render function
<div onClick={this.toggleNotifications} className='bell' id='bell'>
<Glyphicon glyph='bell' id='bell'></Glyphicon>
{
this.state.store.state.unreadCount > 0 ?
<span className='notBadge' id='bell'><span id='bell'>{this.state.store.state.unreadCount}</span></span>
: null
}
</div>
<div id='notificationsPanel' className='notificationsPanel'>
<NotificationsList list={this.state.notificationsData.notifications} clickHandler={this.clickHandler}/>
<div className='footer notification_bar'>
<span className='pull-left'><a onClick={this.seeAll}>See all</a></span>
<span className='pull-right'><a onClick={this.markAllRead}>Mark all as read</a></span>
</div>
</div>
... ...
updateReadStatus: function(){
notificationsStore.markAllRead();
},
markAllRead: function(){
ActionsNotifications.markAllRead().then(this.updateReadStatus); // API call
},
In function updateReadStatus
I am calling the store method (markAllRead) manually. What's the correct way to trigger action as I am already listening to them in store ?
Second, I am receiving the store state currently as this.state.store.state.someVariable
. How can I make life simple in getInitialState
or any if any other function to just to do this.state.someVariable
? The line commented in getInitialState can be useful in constructor(){} but not here in my set up of createClass()
Thanks!
Upvotes: 4
Views: 433
Reputation: 10837
It's not very clear which version of Reflux you are using, but I will try to give you a general overview of how you can make this work...
Reflux is a very simple flux implementation, you have a very linear flow of control -
Component -(invoke)-> Action -(handle-in)-> Store -(trigger)-> Component
With this in mind, you need to follow some very simple guidelines. Any component must only use Action to trigger a state change in store. The store in turn must use trigger
function to trigger component re-render when its state is updated. So you only need to call the markAllRead
method in your component which is invoking the action in-turn.
And on the long store reference issue... You should be able to use the various Component - Store connection mechanisms to make it less verbose. Now this is where it will depend on your version of Reflux, but the below should work -
Use the connect
mixin to have your Component connected with the Store so that it not only re-renders on a Store trigger
call, but also exposes the Store state on a given state variable. A simple example is -
var HeaderComponent = React.createClass({
mixins: [Reflux.connect(notificationStore,"notifications")],
render: function() {
// Use "this.state.notifications.unreadCount" etc.
}
});
Hope this helps.
Upvotes: 1