vendredi 24 juillet 2015

Managing UI feedback in React.js

Is there an established pattern used to manage user interactions with individual components, such as displaying loader spinners, disabling input fields while a form is saving/loading, etc.?

I'm finding myself doing the following in my stores in order to keep components somewhat decoupled from any implied state:

function CampaignStore() { EventEmitter.call(this);

AppDispatcher.register(payload => {
    switch (payload.type) {
        // [#1] ---------------v  (main action)
        case CampaignContants.SAVE:
            // [#2] ------------------------v  (prepare for the main action)
            this.emit(CampaignContants.WILL_SAVE);

            const data = payload.data;
            if (data.id) {
                // [#3] ---v  (perform main action in store)
                updateCampaign(payload.data).then(_ => {
                   // [#4] ------------------------v  (after main action)
                   this.emit(CampaignContants.DID_SAVE, 0)
                });
            } else {
                insertCampaign(payload.data).then(campaignId => this.emit(CampaignContants.DID_SAVE, campaignId));
            }
            break;
        // ...
    }
}

Basically, I just fire an event saying that some action is about to take place, then I perform the action (make API call, etc.), then emit another event when the action completes.

Inside a component, I can just subscribe to a WILL_ event, render all the spinners and such, then clear up the screen when the DID_ is fired. While this seems to work, it does feel pretty boilerplattie and repetitive, as well as super messy (way too much state that only exists to tweak the UI based on where an action is (between WILL_ and DID_

// some component
var MyComponent = React.createClass({
   getInitialState: function () {
       return {
           items: [],
           loading: false,
           saving: false,
           checkingPasswordStrength: fase,
           // ...
       };
   },
   render: function(){
      return (
          <div>
             {this.state.loading && (
                 <p>Loading...</p>
             )}

             {!this.state.loading && (
                 // Display component in not-loading state
             )}
          </div>
      );
   }
});

Aucun commentaire:

Enregistrer un commentaire