我一直在努力寻找解决这个问题的方法......
我正在开发一个带有在线记分牌的游戏.玩家可以随时登录和注销.完成游戏后,玩家将看到记分牌,并查看自己的排名,并自动提交分数.
记分牌显示了玩家的排名和排行榜.
当用户完成播放(提交分数)以及用户只想查看他们的排名时,使用记分板.
这是逻辑变得非常复杂的地方:
如果用户已登录,则将首先提交分数.保存新记录后,将加载记分板.
否则,将立即加载记分板.玩家将获得登录或注册的选项.之后,将提交分数,然后记分板将再次刷新.
但是,如果没有要提交的分数(只需查看高分表).在这种情况下,只需下载播放器的现有记录.但由于此操作不会影响记分牌,因此记分牌和玩家记录应同时下载.
有无限数量的级别.每个级别都有不同的记分牌.当用户查看记分板时,用户正在"观察"该记分板.当它关闭时,用户停止观察它.
用户可以随时登录和注销.如果用户注销,则用户的排名应该消失,如果用户以另一个帐户登录,则应该获取并显示该帐户的排名信息.
...但是,此信息只应针对用户当前正在观察的记分板进行.
对于查看操作,结果应缓存在内存中,以便如果用户重新订阅同一记分板,则不会提取.但是,如果提交了分数,则不应使用缓存.
任何这些网络操作都可能失败,并且播放器必须能够重试它们.
这些操作应该是原子的.所有状态都应该一次更新(没有中间状态).
目前,我能够使用Bacon.js(功能性反应式编程库)来解决这个问题,因为它提供了原子更新支持.代码非常简洁,但现在它是一个混乱的不可预测的意大利面条代码.
我开始看Redux.所以我尝试构建商店,并想出了类似的东西(用YAMLish语法):
user: (user information)
record:
level1:
status: (loading / completed / error)
data: (record data)
error: (error / null)
scoreboard:
level1:
status: (loading / completed / error)
data:
- (record data)
- (record data)
- (record data)
error: (error / null)
Run Code Online (Sandbox Code Playgroud)
问题变成:我在哪里放置副作用.
对于无副作用的动作,这变得非常容易.例如,在LOGOUT行动时,record减速器可以简单地将所有记录都抛出.
但是,某些行为确实有副作用.例如,如果我在提交分数之前没有登录,那么我成功登录,该SET_USER操作将用户保存到商店中.
但是因为我有一个要提交的分数,这个SET_USER动作也必须引发一个AJAX请求,同时设置record.levelN.status为loading.
问题是:当我以原子方式登录时,我如何表示应该发生副作用(得分提交)?
在Elm架构中,更新程序在使用形式时也会发出副作用 …
使用同构应用程序设置应用程序的初始状态的一般做法是什么?没有Flux我会简单地使用类似的东西:
var props = { }; // initial state
var html = React.renderToString(MyComponent(props);
Run Code Online (Sandbox Code Playgroud)
然后通过快速把手渲染该标记并显示通过{{{reactMarkup}}.
在客户端设置初始状态我会做这样的事情:
if (typeof window !== 'undefined') {
var props = JSON.parse(document.getElementById('props').innerHTML);
React.render(MyComponent(props), document.getElementById('reactMarkup'));
}
Run Code Online (Sandbox Code Playgroud)
所以基本上你是在服务器和客户端上设置状态两次,但是React会比较这些差异,在大多数情况下,它不会通过重新渲染来影响性能.
当您在Flux架构中拥有操作和存储时,此原则将如何工作?在我的组件里面我可以做到:
getInitialState: function() {
return AppStore.getAppState();
}
Run Code Online (Sandbox Code Playgroud)
但是现在我如何从服务器设置AppStore中的初始状态?如果我使用React.renderToString没有传递的属性,它将调用AppStore.getAppState()哪个不会有任何内容,因为我仍然不明白我将如何在服务器上的商店中设置状态?
我仍在寻找一种干净的解决方案,不涉及使用Fluxible,Fluxxor,Reflux等第三方Flux实施.
使用Redux.
这是代码 actions.js
export function exportRecordToExcel(record) {
return ({fetch}) => ({
type: EXPORT_RECORD_TO_EXCEL,
payload: {
promise: fetch('/records/export', {
credentials: 'same-origin',
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(function(response) {
return response;
})
}
});
}
Run Code Online (Sandbox Code Playgroud)
返回的响应是一个.xlsx文件.我希望用户能够将其保存为文件,但没有任何反应.我假设服务器正在返回正确类型的响应,因为它在控制台中说
Content-Disposition:attachment; filename="report.xlsx"
Run Code Online (Sandbox Code Playgroud)
我错过了什么?我该怎么做减速机?

据我所知,这张图片是大多数(如果不是全部)Flux程序员的终极指南.考虑到这一点,我有几个问题:
$.ajax在我的Web API Utils中调用所有调用是否正确/强烈建议?
在我的一个Action Creators中是否可以使用逻辑(知道要调度哪个Action)?基本上,此操作接收来自我的AJAX调用的响应.这是一个片段:
var TransportActions = {
receiveProxyMessage: function (message, status, xhr) {
switch (message) {
case ProxyResponses.AUTHORIZED:
AppDispatcher.dispatch({
type: ActionTypes.LOGIN_SUCCESS,
reply: m
});
break;
case ProxyResponses.UNAUTHORIZED:
AppDispatcher.dispatch({
type: ActionTypes.LOGIN_FAIL,
reply: m
});
break;
...
}
} …Run Code Online (Sandbox Code Playgroud)Egghead教程教导它像这样:
var React = require('react');
var Router = require('react-router');
var routes = require('./config/routes');
Router.run(routes, function(Root){
React.render(<Root />, document.getElementById('app'));
});
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个错误:
未捕获的TypeError:Router.run不是函数
注意:我已经更新react-router到最新版本.
我对这些语句感到有点困惑:"呈现整个应用程序"和"将状态传递给子组件".
我有一个带有AppComponent和的todos应用程序TodosListComponent.该AppComponent抓斗从商店待办事项的阵列,并将其作为一个属性的TodosListComponent.
我有很多状态的巨大应用程序.我有50个组件构建我的应用程序.我想AppComponent通过所有50个组件将所有状态从商店中传递下来吗?
所以我想知道,会议是什么?让个别组件直接听他们关心的商店对我来说更有意义.优点是只有单个组件重新渲染,但为什么然后"整个应用程序在状态变化上重新渲染"的概念呢?
各自的优点和缺点是什么?常见的惯例是什么?
我正在尝试将Backbone.Marionette应用程序替换为React,并且在查询查询参数时遇到困难.我想我在理解这种模式时错过了一种非常简单的和平,所以如果这个问题完全是胡说八道,我会道歉.我会感谢任何支持,或者只是指出我可以更具体地谷歌的一些方向.
有一个/users列出用户的页面,您可以通过搜索栏过滤用户.因此,如果您想过滤用户名中包含"joe"的用户,我会向查询参数的服务器发出请求/users?username=joe.另外,我也可以通过添加page参数(/users?username=joe&page=1)来分页.
如果我只考虑功能,那么流程可能就是
joe到input元素并单击" 搜索".Action(如Action.getUser).Action向服务器请求并接收结果Dispatcher结果有效负载的函数调度给任何(通常是Store)感兴趣的人Action.Store与新的结果通过接收到的状态变化ActionComponent)通过聆听Store改变来重新渲染.它按预期工作.但是,我希望客户能够为当前过滤的结果添加书签,并且能够在一段时间之后返回到同一页面.这意味着我需要在某处保存关于客户所做搜索词的明确信息,这通常是网址(我是对的吗?).所以我需要用查询参数更新url以保存搜索词(/users?username=joe&page=1).
我感到困惑的是在何时何地更新网址?我现在能想到的是下面的两个选项 - 它们似乎根本不干净.
joe到input元素并单击" 搜索"./users?username=joe&page=1)触发ReactRouter的转换.Component)通过this.props.params和接收新的参数this.props.query.Component)根据它收到的查询参数触发Action类似的Action.getUser东西 - 在这种情况下username=joe&page=1.在此之后,它与上面相同
joe到input元素并单击" …我axios用于ajax请求和reactJS+ flux用于渲染UI.在我的应用程序中有第三个时间轴(reactJS组件).时间轴可以通过鼠标滚动来管理.应用程序在任何滚动事件后发送实际数据的ajax请求.服务器上的请求处理可能比下一个滚动事件更慢的问题.在这种情况下,应用程序可以有几个(通常2-3个)已经弃用的请求,因为用户进一步滚动.这是一个问题,因为每次接收新数据时间线都会开始重绘.(因为它是reactJS + flux)因此,用户会多次来回看时间轴的移动.解决此问题的最简单方法是,它只是中止以前的ajax请求jQuery.例如:
$(document).ready(
var xhr;
var fn = function(){
if(xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: 'ajax/progress.ftl',
success: function(data) {
//do something
}
});
};
var interval = setInterval(fn, 500);
);
Run Code Online (Sandbox Code Playgroud)
如何取消/中止请求axios?
flux ×10
reactjs ×9
javascript ×6
reactjs-flux ×3
react-router ×2
redux ×2
ajax ×1
axios ×1
es6-promise ×1
express ×1
refluxjs ×1
url-routing ×1