Search code examples
reactjsreactjs-fluxfluxible

How to adapt the standard react-notification-system example to a fluxible project


I'm trying to use this component https://github.com/igorprado/react-notification-system in a standard fluxible project and am looking for guidance on how to adapt the sample code into an es6 style class.

Here's the original sample code:

var React = require('react');
var ReactDOM = require('react-dom');
var NotificationSystem = require('react-notification-system');

var MyComponent = React.createClass({
  _notificationSystem: null,

  _addNotification: function(event) {
    event.preventDefault();
    this._notificationSystem.addNotification({
      message: 'Notification message',
      level: 'success'
    });
  },

  componentDidMount: function() {
    this._notificationSystem = this.refs.notificationSystem;
  },

  render: function() {
    return (
      <div>
        <button onClick={this._addNotification}>Add notification</button>
        <NotificationSystem ref="notificationSystem" />
      </div>
      );
  }
});

ReactDOM.render(
  React.createElement(MyComponent),
  document.getElementById('app')
);

And here's my attempt to add it to a fluxible application component, should I add the notificationSystem object into state? Is using componentDidMount always reliable if I'm connecting to stores? How should I trigger the notification from an action - should I update a notificationStore that triggers the component or act on the component directly somehow from the action itself?

class Application extends React.Component {

    //constructor(props) {
    //    super(props);
    //    this.state = {
    //        notificationSystem: this.refs.notificationSystem
    //    };
    //}

    addNotification(event) {
        event.preventDefault();
        this.notificationSystem.addNotification({
            message: 'Notification message',
            level: 'success'
        });
    }

    render() {
        var Handler = this.props.currentRoute.get('handler');

        return (
            <div>
                <Nav currentRoute={this.props.currentRoute} links={pages} />
                <div className="main">
                    <Handler />
                </div>
                <NotificationSystem ref="notificationSystem" />
            </div>
        );
    }

    componentDidMount() {
        this.state.notificationSystem = this.refs.notificationSystem;
    }

    componentDidUpdate(prevProps, prevState) {
        const newProps = this.props;
        if (newProps.pageTitle === prevProps.pageTitle) {
            return;
        }
        document.title = newProps.pageTitle;
    }
}

Solution

  • You can store it on a property of your Application:

    class Application extends React.Component {
    
        //constructor(props) {
        //    super(props);
        //    this.state = {
        //        notificationSystem: this.refs.notificationSystem
        //    };
        //}
    
        notificationSystem = null;
    
        componentDidMount() {
            this.notificationSystem = this.refs.notificationSystem;
        }
    
        addNotification(event) {
            event.preventDefault();
            this.notificationSystem.addNotification({
                message: 'Notification message',
                level: 'success'
            });
        }
    

    Or if you want a more complete example using flux pattern:

    This answer was based on: https://github.com/igorprado/react-notification-system/issues/29#issuecomment-157219303

    React component that will trigger the notification:

    _saveFileStart() {
        this.props.flux.getActions('notification').info({
          title: 'Saving file',
          message: 'Please wait until your file is saved...',
          position: 'tc',
          autoDismiss: 0,
          dismissible: false
        });
      }
    ...
    render() {
        <button onClick={ this._saveFileStart.bind(this) }>Save file</button>
    }
    

    Notification actions, there is a .info() alias to trigger notifications with level info

    constructor() {
        this.generateActions('add', 'remove', 'success', 'error', 'warning', 'info');
    }
    

    (I'm using the alt generator to generate the add action, remove and some aliases)

    Notification store

    constructor() {
        this.bindActions(this.alt.getActions('notification'));
    
        this.state = {
          notification: null,
          intent: null
        };
      }
    ...
      onInfo(notification) {
        return this._add(notification, 'info');
      }
    ...
      _add(notification, level) {
        if (!notification) return false;
        if (level) notification.level = level;
        return this.setState({ notification, intent: 'add' });
      }
    

    React component that will render the Notification component on a top level HTML element

    componentDidMount() {
        const { flux } = this.props;
        flux.getStore('notification').listen(this._handleNotificationChange);
    }
    ...
      _handleNotificationChange = ({ notification, intent }) => {
        if (intent === 'add') {
          this.refs.notifications.addNotification(notification);
        }
      };
    ...
      render() {
        return <ReactNotificationSystem ref='notifications' />;
      }
    

    This answer was based on: https://github.com/igorprado/react-notification-system/issues/29#issuecomment-157219303