javascript - ReactJS + Flux - Hur implementerar man toasts/aviseringar?


Jag försöker förstå Flux och Reactjs.

Tänk på följande mycket enkla scenario:

Du har ett formulär med få inmatningar. När användaren skickar in formuläret,

ActionCreator.publishAnnouncement(this.state.announcement);

kallas inuti min formulärkomponent. Så här ser publishAnnouncement-metoden ut:

var publishAnnouncement = function (announcement) {
  AnnouncementAPI.publishAnnouncement(
    announcement,
    successCallback,
    failureCallback
  )
};

AnnouncementAPI är bara ett omslag runt ett AJAX HTTP POST-anrop. Det tar två återuppringningar - vid framgång och vid misslyckande.

Och nu: Jag behöver visa en notifikation/toast på skärmen - som indikerar framgång eller misslyckande. Hur skulle du göra det på ett Flux-sätt?

Jag funderade på att skapa en Notification-komponent och rendera den inne i mitt formulär. Som följande:

<Notification title={this.state.notification.title} message={this.state.notification.title} visible={this.state.notification.visibility}  // ?? onTimeExceeded ??     />

Men hur hanterar jag dessa återuppringningar? Ska jag skapa NotificationStore som lyssnar på ANNOUNCEMENT_PUBLISHING_SUCCEEDED och ANNOUNCEMENT_PUBLISHING_FAILED händelser? Som en reaktion på dessa händelser, sänder store ett CHANGE-event och på så sätt uppdateras mitt Notification.

Men även om jag gör det, hur ska jag instruera min Notifikation att visa/dölja sig? Eller ännu värre, att dyka upp och försvinna efter 2 sekunder?

Jag har sett några komponenter på GitHub och var och en av dem använder refs osv, vilket jag personligen inte tycker om.

Sammanfattningsvis: Hur skulle du implementera detta? Eller kanske finns ett sådant projekt? Om så är fallet, var kan jag hitta det?

Svar #1

Jag ser inget fel med att ha en butik enbart för aviseringar, särskilt om du vill ha logik kring att visa/dölja aviseringar på timers, visa flera aviseringar, etc.

Det finns två sätt jag skulle överväga att skriva detta på:

  1. Bind NotificationStore direkt till de success-/failure-callbacks du bryr dig om, som du nämnde i din fråga. Inte säker på vilken flux-implementation du använder, så det här blir lite som pseudokod.

    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");
      }
    }
    
  2. Ange de aviseringar du vill ha i dina action creators. Detta är mer explicit men mindre centraliserat.

    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!"
          });
        }
      )
    };
    

    I det här fallet skulle NotificationStore se i princip likadan ut, men utan att binda till varje enskild success/fail-åtgärd. I båda fallen skulle jag ha en enda Notifications-widget nära toppen av min komponentträd som renderade listan med notifikationer.

Svar #2

Till försvar för refs (och som författare till den länkade GitHub-repot): Dina butiker skulle kunna avge ett event när de ändras, vilket skulle ha en handler i komponenten. Denna handler skulle sedan utlösa notisen via ref. Det är mycket mindre komplext att låta din komponent hantera notisen genom refs istället för props.