javascript Redux reducers 和 action creators 之间的逻辑如何划分?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34098125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 17:14:33  来源:igfitidea点击:

How to divide the logic between Redux reducers and action creators?

javascriptreactjsredux

提问by user3224271

I have some logic that I've put in the reducer which I'm thinking should be possibly put in the Action and passed down?

我有一些我已经放入减速器的逻辑,我认为应该可能放入 Action 并传递下去?

Is it best practice to put this sort of stuff in the actions or reducer?

将这种东西放在动作或减速器中是最佳实践吗?

Working example here.

工作示例在这里

Reducer code:

减速机代码:

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
  }
}

回答by Dan Abramov

Your reducer must be pure. Currently it is not pure. It calls deal()which calls getRandom()which relies on Math.random()and thus is not pure.

你的减速机必须是纯的。目前它不纯。它调用deal()which 调用getRandom()which 依赖Math.random(),因此不是纯的。

This kind of logic (“generating data”, whether randomized or from user input) should be in the action creator. Action creators don't need to be pure, and can safely use Math.random(). This action creator would return an action, an object describing the change:

这种逻辑(“生成数据”,无论是随机的还是来自用户输入的)应该在动作创建者中。动作创建者不需要是纯粹的,并且可以安全地使用Math.random(). 这个动作创建者将返回一个动作,一个描述变化的对象

{
  type: 'DEAL_CARDS',
  cards: ['heart', 'club', 'heart', 'heart']
}

The reducer would just add (or replace?) this data inside the state.

减速器只会在状态中添加(或替换?)这些数据。

In general, start with an action object.It should describe the change in such a way that running the reducer with the same action object and the same previous state should return the same next state. This is why reducer cannot contain Math.random()calls—they would break this condition, as they would be random every time. You wouldn't be able to test your reducer.

一般来说,从一个动作对象开始。它应该以这样一种方式来描述变化,即使用相同的动作对象和相同的前一个状态运行减速器应该返回相同的下一个状态。这就是 reducer 不能包含Math.random()调用的原因——它们会破坏这个条件,因为它们每次都是随机的。您将无法测试您的减速器。

After you figure out how the action object looks (e.g. like above), you can write the action creator to generate it, and a reducer to transform state and action to the next state. Logic to generate an action resides in action creator, logic to react to it resides in the reducer, reducer must be pure.

在弄清楚 action 对象的外观后(例如像上面那样),您可以编写 action creator 来生成它,并编写一个 reducer 来将 state 和 action 转换为下一个状态。生成动作的逻辑驻留在动作创建者中,对其作出反应的逻辑驻留在reducer中,reducer必须是纯的。

Finally, don't use classes inside the state. They are not serializable as is. You don't need a Cardclass. Just use plain objects and arrays.

最后,不要在 state 内部使用类。它们不能按原样序列化。你不需要Card上课。只需使用普通对象和数组。

回答by Mark McKelvy

My understanding is that actions should be simple objects that contain two things: (i) the action type and (ii) what changed (i.e. the new data).

我的理解是动作应该是包含两件事的简单对象:(i)动作类型和(ii)改变了什么(即新数据)。

Reducers on the other hand, are pure functions that take actions and the previous app state as inputs and return the new app state. How they accomplish this is up to you. You can add whatever logic necessary to take the combination of previous state + action and return the new state as long as you don't mutate data outside your reducer function(s).

另一方面,Reducer 是纯函数,它将操作和之前的应用程序状态作为输入并返回新的应用程序状态。他们如何实现这一点取决于您。您可以添加任何必要的逻辑来采用先前状态 + 操作的组合并返回新状态,只要您不改变减速器函数之外的数据即可。

As for your code specifically, I'm not sure the deal()function belongs in either an action or a reducer. I think a better place might be in some sort of event handler (e.g. onClick). You could then pass the resultsof the deal call as an action to your reducer.

至于您的代码,我不确定该deal()函数属于动作还是减速器。我认为更好的地方可能是在某种事件处理程序中(例如onClick)。然后,您可以将交易调用的结果作为操作传递给您的减速器。

回答by Mardo

It appears then it's a best practice to have an static class that handles the first level entery points that instantiates the redux actions outside of the redux.

看来最好有一个静态类来处理在 redux 之外实例化 redux 操作的第一级输入点。

I suppose that makes sense to keep the store and action chains pure.

我认为保持 store 和 action 链的纯净是有意义的。

This might look like a lot of replicated code at first but when you start dispatching based on conditions or need to dispatch from multiple places it starts to open up and make sense.

一开始这可能看起来像很多重复的代码,但是当您开始根据条件分派或需要从多个地方分派时,它开始开放并有意义。