I'm trying to understand Flux and Reactjs.
Consider a following, very simple scenario:
You have a form with few inputs. When user submits form,
ActionCreator.publishAnnouncement(this.state.announcement);
is called inside my form component. This is how the publishAnnouncement method looks like:
var publishAnnouncement = function (announcement) {
  AnnouncementAPI.publishAnnouncement(
    announcement,
    successCallback,
    failureCallback
  )
};
AnnouncementAPI is just a wrapper upon an AJAX http POST call. It takes two callbacks - on success and on failure.
And now: I need to show a notification/toast on the screen - indicating success or failure. How would you do that in a Flux way?
I was thinking about creating Notification component and rendering it inside my form. Like the following:
<Notification title={this.state.notification.title} message={this.state.notification.title} visible={this.state.notification.visibility}  // ?? onTimeExceeded ??     />
But how do I handle those callbacks? Should I create NotificationStore which listens for ANNOUNCEMENT_PUBLISHING_SUCCEEDED and ANNOUNCEMENT_PUBLISHING_FAILED events? In reaction to those events, store emits CHANGE event and thus my Notification updates.
But even if I do that, how should I instruct my Notification to show/hide? Or worse, to show up and hide after 2 seconds?
I've seen few components on GitHub and each of them uses refs etc, which I personally don't like.
To sum up: How would you implement this? Or maybe such project exists? If so, where can I find it?
I don't see anything wrong with having a store solely for notifications, especially if you want logic around showing/hiding notifications on timers, showing multiple notifications, etc.
There are two ways I would consider writing this:
Bind the NotificationStore directly to the success/failure callbacks you care about, like you mentioned in your question. Not sure what flux implementation you're using, so this will be pseudocode-y.
class NotificationStore {
  constructor() {
    this.notificationId = 0;
    this.notifications = {};
    this.bindActionType(
      CLEAR_NOTIFICATION,
      this.handleClearNotification
    );
    this.bindActionType(
      ANNOUNCEMENT_PUBLISHING_SUCCEEDED,
      this.handleAnnouncementPublishingSucceeded
    );
    // etc...
  }
  handleAnnouncementPublishingSucceeded(action) {
    this.addNotification("Success!", { timeout: 2000 });
  }
  handleClearNotification(action) {
    this.removeNotification(action.notificationId);
  }
  addNotification(message, options) {
    const nextId = this.notificationId++;
    const notification = {
      message: message
    };
    this.notifications[nextId] = notification;
    this.emit("change");
    // if we specified a timeout, remove the notification
    // after the timeout expires.
    if (options.timeout) {
      setTimeout(() => {
        dispatch(CLEAR_NOTIFICATION, {
          notificationId: nextId
        });
      }, options.timeout);
    }
  }
  removeNotification(notificationId) {
    delete this.notifications[nextId];
    this.emit("change");
  }
}
Specify the notifications you want in your action creators. This is more explicit but less centralized.
var publishAnnouncement = function (announcement) {
  AnnouncementAPI.publishAnnouncement(
    announcement,
    (response) => {
      dispatch(ANNOUNCEMENT_PUBLISHING_SUCCEEDED, ...);
      dispatch(CREATE_NOTIFICATION, {
        message: "Success!",
        timeout: 2000
      });
    },
    (error) => {
      dispatch(ANNOUNCEMENT_PUBLISHING_FAILED, ...);
      dispatch(CREATE_NOTIFICATION, {
        message: "Failure!"
      });
    }
  )
};
In this case, the NotificationStore would look basically the same, but without binding to each and every success/fail action. In either case, I would have a single Notifications widget near the top of my component tree that rendered the list of notifications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With