如何划分Redux Reducer与动作创建者之间的逻辑?

时间:2015-12-04 21:53:52

标签: javascript reactjs redux

我有一些逻辑,我已经把它放在减速器中,我认为应该把它放在动作中并传下来?

将这类东西放入动作或减速器中是最佳做法吗?

工作示例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
  }
}

3 个答案:

答案 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动作。

我认为保持商店和行动链的纯洁是有道理的。

这可能看起来像很多复制代码,但是当你根据条件开始调度或需要从多个地方发送时,它开始开放并且有意义。