我有一些逻辑,我已经把它放在减速器中,我认为应该把它放在动作中并传下来?
将这类东西放入动作或减速器中是最佳做法吗?
工作示例here。
减速机代码:
function Card() {
this.card = (Math.random()*4).toFixed(0);
}
Card.prototype = {
getRandom: function(){
var card;
//console.log(this.card)
switch (this.card) {
case '1':
card = 'heart';
break;
case '2':
//card = 'diamonds';
card = 'heart'; // weight the odds abit
break;
case '3':
card = 'club';
break;
case '4':
card = 'spade';
break;
default:
card = 'heart';
break;
}
return card;
}
}
var dealer = {
deal: function(){
var results = [];
for(var i = 0; i <4; i++){
var card = new Card();
results.push(card.getRandom());
}
console.log(results);
return results;
}
}
const initialState = {
count: 0,
data: []
}
function counter (state = initialState, action) {
let count = state.count
switch (action.type) {
case 'increase':
return Object.assign({}, state, {
data: dealer.deal(),
count: state.count+1
})
default:
return state
}
}
答案 0 :(得分:63)
你的减速机必须是纯净的。目前它并不纯粹。它调用deal()
调用getRandom()
,该Math.random()
依赖于Math.random()
,因此不是纯粹的。
这种逻辑(“生成数据”,无论是随机的还是来自用户输入的)都应该在动作创建者中。动作创建者不需要是纯粹的,并且可以安全地使用{
type: 'DEAL_CARDS',
cards: ['heart', 'club', 'heart', 'heart']
}
。此操作创建者将返回一个操作,描述更改的对象:
Math.random()
reducer只会在状态中添加(或替换?)这些数据。
通常,以操作对象开始。它应该以这样的方式描述更改,即使用相同的操作对象和相同的先前状态运行reducer应该返回相同的下一个状态。这就是reducer不能包含Card
次调用的原因 - 它们会破坏这种情况,因为它们每次都是随机的。你将无法测试减速器。
在弄清楚动作对象的外观(例如上面的内容)后,您可以编写动作创建器来生成动作对象,并使用减速器将状态和动作转换为下一个状态。 生成动作的逻辑驻留在动作创建者中,对其作出反应的逻辑驻留在reducer中,reducer必须是纯粹的。
最后,不要在州内使用类。它们不是可序列化的。您不需要{{1}}课程。只需使用普通对象和数组。
答案 1 :(得分:0)
我的理解是,操作应该是包含两件事的简单对象:(i)操作类型和(ii)更改的内容(即新数据)。
另一方面,Reducers是纯函数,它将操作和先前的app状态作为输入并返回新的app状态。他们如何实现这一点取决于你。您可以添加任何必要的逻辑来结合先前的状态+操作并返回新状态,只要您不在变换器函数之外变异数据。
至于具体的代码,我不确定deal()
函数属于action还是reducer。我认为更好的地方可能是某种事件处理程序(例如onClick
)。然后,您可以将交易调用的结果作为操作传递给reducer。
答案 2 :(得分:0)
然后看来,最好的做法是使用一个静态类来处理第一级entery点,这些点实例化redux之外的redux动作。
我认为保持商店和行动链的纯洁是有道理的。
这可能看起来像很多复制代码,但是当你根据条件开始调度或需要从多个地方发送时,它开始开放并且有意义。