HalfWebDev
HalfWebDev

Reputation: 7648

Hook Reflux store in React.createClass and trigger actions the right way

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

Answers (1)

hazardous
hazardous

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

Related Questions