我正在分解Redux的todo示例以试图理解它.我读过,mapDispatchToProps允许你将调度动作映射为道具,所以我想重写addTodo.js使用mapDispatchToProps而不是调用dispatch(addTodo()).我打电话给它addingTodo().像这样的东西:
import React from 'react';
import {connect} from 'react-redux';
import addTodo from '../actions';
let AddTodo = ({addingTodo}) => {
let input;
return (
<div>
<form onSubmit={e => {
e.preventDefault()
if (!input.value.trim()) {
return
}
addingTodo(input.value)
input.value = ""
}}>
<input ref={node => {
input = node
}} />
<button type="submit">Submit</button>
</form>
</div>
)
}
const mapDispatchToProps = {
addingTodo: addTodo
}
AddTodo = connect(
mapDispatchToProps
)(AddTodo)
export default AddTodo
Run Code Online (Sandbox Code Playgroud)
但是,当我运行应用程序时,我收到此错误:Error: Invalid value of …
我开发的应用程序最初是使用Flux构建的.
但是,随着时间的推移,应用程序变得更难维护.有很多行动.通常只在一个地方(商店)收听一个动作.
操作可以不在一个地方编写所有事件处理程序代码.所以不是这样的:
store.handleMyAction('ha')
another.handleMyAction('ha')
yetAnotherStore.handleMyAction('ha')
Run Code Online (Sandbox Code Playgroud)
我可以写:
actions.myAction('ha')
Run Code Online (Sandbox Code Playgroud)
但我从不以这种方式使用行动.我几乎可以肯定,这不是我申请的问题.
每次我打电话给一个动作,我都可以打电话store.onSmthHappen而不是action.smthHappen.
当然,在一些地方处理一个动作时也有例外.但是当发生这种情况时,感觉就像出了问题.
如果不是调用动作而是直接从商店调用方法呢?我的申请会不会那么灵活?没有!仅发生重命名(极少数例外).但是要付出什么代价!通过所有这些操作来理解应用程序中发生的事情变得更加困难.每次跟踪复杂动作的处理时,我都必须在商店中找到它们的处理方式.然后在这些商店中我应该找到调用另一个动作的逻辑.等等.
现在我来解决我的问题:
有控制器直接从商店调用方法.所有的逻辑如何处理行动是在商店.还存储对WebAPI的调用(通常是与一个WebAPI相关的一个商店).如果事件应该在几个商店中处理(通常是顺序的),那么控制器通过编排从商店返回的承诺来处理这个事件.私有方法中的一些序列(常用).控制器的方法可以将它们用作处理的简单部分.所以我永远不会复制代码.
控制器方法不返回任何内容(单向流).
实际上,控制器不包含如何处理数据的逻辑.它只是指向哪里,以什么顺序.
您几乎可以看到商店中数据处理的完整图片.商店里没有关于如何与其他商店互动的逻辑(通过它就像一个多对多的关系,但只是通过行动).现在,商店是一个高度凝聚力的模块,只负责域模型(集合)的逻辑.
主要(在我看来)助焊剂的优势仍然存在.
因此,有商店,这是唯一真正的数据来源.组件可以订阅商店.组件调用与以前相同的方法,但不是actions使用controller.与React的交互根本没有改变.
此外,事件处理变得非常明显.现在我可以看一下控制器中的处理程序,一切都变得清晰,调试起来要容易得多.
问题是:
为什么行动创造了变化?他错过了哪些优势?
我读过FRP,非常兴奋.它看起来很棒,所以你可以编写更多高级代码,一切都更具可组合性等.
然后我试图用普通的js到Bacon重写我自己的小游戏.
我发现不是编写高级逻辑代码,而是使用Bacon.js并遵守原则.
我遇到了一些令人头痛的问题,主要是干扰代码
.take(1)我应该创造丑陋的结构,而不是获得价值.
有时它们应该是逻辑的.但在FRP中实施它是可怕的
即使是bacon.js的创造者也会遇到麻烦.
这里的例子是代码的和平来证明问题:
任务是不允许两名球员留在同一个地方
用bacon.js实现
http://jsbin.com/zopiyarugu/2/edit?js,console
function add(a) {return function(b){return a + b}}
function nEq(a) {return function(b){return a !== b}}
function eq(a) {return function(b){return a === b}}
function always(val) {return function(){return val}}
function id(a){return a}
var Player = function(players, movement, initPos){
var me = {};
me.position = movement
.flatMap(function(val){
return me.position
.take(1)
.map(add(val))
})
.flatMap(function(posFuture){
var otherPlayerPositions = players
.filter(nEq(me))
.map(function(player){return player.position.take(1)})
return Bacon
.combineAsArray(otherPlayerPositions)
.map(function(positions){
return !positions.some(eq(posFuture));
})
.filter(id) …Run Code Online (Sandbox Code Playgroud) 我正在编写一个组件,它将对站点的两个不同路径进行提取请求,然后将其状态设置为生成的响应数据.我的代码看起来像这样:
export default class TestBeta extends React.Component {
constructor(props){
super(props);
this.state = {
recentInfo: [],
allTimeInfo: []
};
}
componentDidMount(){
Promise.all([
fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent'),
fetch('https://fcctop100.herokuapp.com/api/fccusers/top/alltime')
])
.then(([res1, res2]) => [res1.json(), res2.json()])
.then(([data1, data2]) => this.setState({
recentInfo: data1,
alltimeInfo: data2
}));
}
Run Code Online (Sandbox Code Playgroud)
但是,当我去渲染我的两个状态时,我发现它们实际上仍然是空的,实际上并没有被设置为任何东西.我觉得我可能正在使用Promises或fetch()API错误,或者误解了setState的工作原理,或者是组合的东西.我测试了周围,发现在第一个then()后,我的data1和data2仍然是Promises由于某种原因,并且还没有成为真正的JSON对象.无论哪种方式,我无法弄清楚我的生活在这里发生了什么.任何帮助或解释将不胜感激
javascript ×3
reactjs ×3
bacon.js ×1
fetch ×1
frp ×1
promise ×1
react-redux ×1
reactjs-flux ×1
redux ×1