React/Flux way to handle permission sensitive actions with login flows

蓝咒 提交于 2019-12-20 20:28:19

问题


I have been playing with React/Flux, and I am having trouble wrapping my head around the 'Flux Way' for handling permission-sensitive actions.

Overarching question: When a non-logged in visitor attempts an action that requires he/she to be logged in, what is the Flux way of (a) checking if a user is logged in, (b) starting the login flow, (c) finishing the action on success?

Take an example of a forum app, that requires users to be logged in to post:

We have a comment form component (mostly taken from FB's React tut) as such:

var CommentForm = React.createClass({
  handleSubmit: function ( e ) {
    e.preventDefault();

    // get data
    commentData = {
      content: this.refs.content.getDOMNode().value.trim()
    };

    this.props.onCommentSubmit( commentData );
    this.resetForm();
  },

  resetForm: function () {
    this.refs.content.getDOMNode().value = '';
  },

  render: function () {
    return (
      <form className="comment-form" id="comment-form" onSubmit={ this.handleSubmit }>
        <textarea name="comment[content]" placeholder="What's on your mind?" ref="content"></textarea>
        <button className="post-comment button" type="submit">Post</button>  
      </form>
    )
  }
});

A comments store (abbreviated)

var CHANGE_EVENT = 'change';
var _comments = {};

function createComment ( data ) {
  // post to server
}

var CommentStore = React.addons.update(EventEmitter.prototype, {$merge: {

  // omitted methods

  dispatcherIndex: AppDispatcher.register(function(payload) {
    var action = payload.action;
    var text;

    switch(action.actionType) {
      case CommentConstants.ADD_COMMENT:
        AppDispatcher.waitFor([SessionStore.dispatchToken])
        createComment(action.data);
        break;
    }

    return true;
  })
}});

And a store for handling sessions (also abbreviated):

var CHANGE_EVENT = 'change';

function ensureCurrentUser () {
  if ( !SessionStore.currentUser() ) {
    app.router.navigate('/login');
  }
}

var SessionStore = React.addons.update(EventEmitter.prototype, {$merge: {

  // omitted code

  currentUser: function () {
    return app.context.current_user;
  },

  dispatchToken: AppDispatcher.register(function ( payload ) {
    var action = payload.action;

    switch(action.actionType) {
      case CommentConstants.ADD_COMMENT:
        ensureCurrentUser();
        break;
    }

    return true;
  })
}});

My initial thought was that this is a case for Flux's waitFor() method. However, the implementation above fails, as waitFor closes the dependency loop as soon as SessionStore.dispatchToken is set (as soon as ensureCurrentUser returns).

Is this a case where the payload should be passed into ensureCurrentUser, and then into the route handler for /login? What is the Flux way of handling these types of flows?

Thanks in advance :)


回答1:


As FakeRainBrigand suggested in his answer, you'd want to just check that the user has a valid session before creating a comment by first retrieving that value from the SessionStore:

case CommentConstants.ADD_COMMENT:
  if (SessionStore.getUser()) {
   createComment(action.data);
  }
  break;

But to preserve the comment so that it gets created after the user logs in, I would create a collection of pending comments in the CommentStore, and then later, in a callback to the login verification and session creation, dispatch a new action to inform the CommentStore that the user has now logged in. Then the CommentStore can respond to that by creating real comments out of the pending ones.




回答2:


The simplest would be just asking SessionStore if there's a session.

 case CommentConstants.ADD_COMMENT:
    if (SessionStore.getUser()) {
       createComment(action.data);
    }
    break;

Of course, this just saves you a server request. The behavior shouldn't be any different than always calling createComment(action.data).

Is this a case where the payload should be passed into ensureCurrentUser, and then into the route handler for /login? What is the Flux way of handling these types of flows?

For this, you might want to have an event emitter that emits a 'login' event.

 case CommentConstants.ADD_COMMENT:
    if (SessionStore.getUser()) {
       createComment(action.data);
    }
    else {
       someEventEmitter.one('login', function(){
           createComment(action.data);
       });
       someEventEmitter.emit('loginRequired');
    }
    break;

And when loginRequired is emitted, if there isn't a user logged in, the login view would be presented.




回答3:


It should be noted that there's an example called auth-flow in react-router repo, that shines light on how this could be done. Although, I'm still trying to make it work for me it is useful to add here.



来源:https://stackoverflow.com/questions/26328949/react-flux-way-to-handle-permission-sensitive-actions-with-login-flows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!