使用登录流处理权限敏感操作的 React/Flux 方式
Posted
技术标签:
【中文标题】使用登录流处理权限敏感操作的 React/Flux 方式【英文标题】:React/Flux way to handle permission sensitive actions with login flows 【发布时间】:2014-12-07 08:47:28 【问题描述】:我一直在使用 React/Flux,但在处理对权限敏感的操作时无法理解“Flux 方式”。
总体问题: 当未登录的访问者尝试要求他/她登录的操作时,Flux 的方式是什么(a)检查用户是否已登录,(b)启动登录流程,(c)完成对成功采取行动?
以论坛应用为例,需要用户登录才能发帖:
我们有一个评论表单组件(主要取自 FB 的 React tut):
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>
)
);
一家 cmets 商店(缩写)
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;
)
);
还有一个用于处理会话的商店(也简称为):
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;
)
);
我最初的想法是,这是 Flux 的 waitFor()
方法的一个案例。但是,上面的实现失败了,因为waitFor
会在设置SessionStore.dispatchToken
后立即关闭依赖循环(只要ensureCurrentUser
返回)。
在这种情况下,负载应该传递到ensureCurrentUser
,然后传递到/login
的路由处理程序中吗?处理这些类型的流的 Flux 方式是什么?
提前致谢:)
【问题讨论】:
【参考方案1】:正如 FakeRainBrigand 在他的回答中所建议的那样,您只需通过首先从 SessionStore 检索该值来检查用户是否具有有效会话,然后再创建评论:
case CommentConstants.ADD_COMMENT:
if (SessionStore.getUser())
createComment(action.data);
break;
但为了保留评论以便在用户登录后创建它,我会在 CommentStore 中创建一个待处理的 cmets 集合,然后在对登录验证和会话创建的回调中,调度一个新操作通知 CommentStore 用户现在已经登录。然后 CommentStore 可以通过从待处理的 cmets 中创建真正的 cmets 来响应。
【讨论】:
问题中的代码还有一些其他不相关的问题:在 DOM 中保持状态是 React 中的代码异味。这一行:this.refs.content.getDOMNode().value.trim()
应该替换为this.state.content
——你应该在this.state
中维护textarea 的状态。另请注意,您的 ContentStore 的 dispatcherIndex
可能应重命名为 dispatchToken
以与 SessionStore 保持一致。
感谢您的额外提示! this.refs.content.getDOMNode().value.trim()
实际上是直接取自 Facebook's React tutorial,在 CommentForm
组件中使用。我是否应该在用户更改评论内容时更新状态,然后在提交时简单地从状态中提取?
嗯,我希望 React 网站上没有那个,因为它与此页面形成对比:facebook.github.io/react/docs/forms.html - 这更接近我处理输入的方式,我在其中维护本地组件的this.state
中的值。另请参阅 Flux-TodoMVC 应用程序以获取更完整的示例。
@fisherwebdev:回复:“然后 CommentStore 可以通过从待处理的 cmets 中创建真正的 cmets 来响应”——这在 Flux 中是如何发生的?我认为商店不应该启动网络活动(至少如果您像我按照***.com/questions/25630611/… 那样将商店保持为哑数据存储库)。商店是否应该回调 Action Creator?但我认为商店不应该发起行动?谢谢!
@LaneRettig 商店不是哑数据存储库。它们是应用程序的所有逻辑应该驻留的地方。从商店发起网络活动没有任何问题。有些人喜欢从动作创建者发起,有些人喜欢从商店发起。这主要是口味问题。与服务器异步通信的重要一点是响应需要调度一个新的操作,而不是直接在存储中处理。【参考方案2】:
最简单的方法就是询问 SessionStore 是否有会话。
case CommentConstants.ADD_COMMENT:
if (SessionStore.getUser())
createComment(action.data);
break;
当然,这只是为您节省了服务器请求。这种行为与总是调用createComment(action.data)
应该没有什么不同。
在这种情况下,负载应该传递给 ensureCurrentUser,然后传递给 /login 的路由处理程序吗?处理这些类型的流的 Flux 方式是什么?
为此,您可能需要一个事件发射器来发出“登录”事件。
case CommentConstants.ADD_COMMENT:
if (SessionStore.getUser())
createComment(action.data);
else
someEventEmitter.one('login', function()
createComment(action.data);
);
someEventEmitter.emit('loginRequired');
break;
当 loginRequired 被发出时,如果没有用户登录,则会显示登录视图。
【讨论】:
领先我 20 秒 ;D 呵呵,一开始我错过了问题中最重要的部分,所以也许我应该多花 20 秒时间阅读它:-) FakeRainBrigand 在此处关于向 SessionStore 询问与SessionStore.getUser()
的会话是正确的。不确定我是否完全同意 EventEmitter 的东西,因为它似乎将应用程序变成了一个 pubsub 架构,并且远离了 Flux。如果您试图保留评论以便在用户登录后创建它,我将在 CommentStore 中创建一个待处理的 cmets 集合,然后发送一个操作以通知 CommentStore 用户现在已经登录。然后商店可以通过从待处理的 cmets 中创建真正的 cmets 来对此做出响应。
是的,我倾向于远离纯粹的助焊剂。如果 fisherwebdev 创建了答案,请接受。
我认为你的回答 + 这些 cmets 是可以接受的 :)【参考方案3】:
值得注意的是,react-router repo 中有一个名为auth-flow 的示例,它阐明了如何做到这一点。虽然,我仍在努力让它对我有用,在此处添加很有用。
【讨论】:
以上是关于使用登录流处理权限敏感操作的 React/Flux 方式的主要内容,如果未能解决你的问题,请参考以下文章
React、Flux、React-Router 调度错误 - 可能的批处理更新解决方案?