redux初始状态作为第一个参数是一个不好的做法

时间:2017-08-13 08:40:03

标签: redux default-value

在redux中,初始状态是通过使用第一个参数state的默认参数提供的,而第二个参数action没有默认值。但是,我认为这是代码气味(其他如Airbnb guidelines),因为你总是需要提供第一个参数(然后使用undefined来获取默认值,这是很麻烦的)。我完全理解你为什么要提供初始状态,但为什么他们不切换参数,所以默认值是第二,以使代码符合通用指南?

// bad
function someReducer(state = 0, action) {
  switch (action.type) {
  default: return state;
}

// good
function someReducer(action, state = 0) {
  switch (action.type) {
  default: return state;
}

redux迫使我们的开发人员使用一种不好的做法,鼓励他们在其他地方做这件事。为什么redux开发人员仍然决定采用这种架构?

更新

为什么将默认设置放在首位的错误实践的原因来自语言设计本身。在JS中,解释器无法分辨开发人员的意图。举个例子:

const giveMe = (goodHuman = true, candy) => (goodHuman && candy) ? 'candy' : 'tea';

那么,我会得到糖果吗?

giveMe(true) // not clear! (but it is 'tea')

我无法使用单个参数访问糖果!但我想开发人员会喜欢我得到一些,对吧?但是,candy始终为undefined,使条件表达式的计算结果为undefined。作为后备,执行else部分。这并不是一个明确的意图,很难猜测开发人员想表达什么。此类代码不会通过我们的审核流程/质量保证。

所以,在下面的例子中,开发人员确保我们可以访问那些糖果,如果我们需要它,并且他相信我们默认是那些应该得到糖果的好人类。:

candy giveMe = (candy, goodHuman = true) => (goodHuman && candy) ? 'candy' : 'tea';
giveMe(true) // finally we get the candy!

由于人们说将默认放在前面是使用redux的最佳练习,因此我认为redux在减速器的签名上有一个糟糕的设计!它可能源于reducer-functions通常具有类似签名的事实,但它们不会使第一个参数成为可选,这没有任何意义!它认为,对于使用undefined调用函数的“最佳实践”,redux是一个糟糕的设计决策。

1 个答案:

答案 0 :(得分:1)

"减速机的签名"作为(state, action)的函数基于您传递给Array.prototype.reduce()的回调签名,例如:

const sum = [1, 2, 3].reduce( (sumInProgress, currentNumber) => {
    return sumInProgress + currentNumber;
});

第一个参数是"累加器"或者"以前的状态"值,第二个参数是"当前项"值。在Redux中,这些值对应于现有状态和当前操作。因此,该函数签名有明确的先例。

至于初始化状态:你可以始终提供应用范围的初始状态作为createStore(rootReducer, preloadedState)的第二个参数。但是,鼓励的方法是每个切片缩减器应该负责提供自己的初始状态,并在调用状态值undefined时这样做。内置的combineReducers函数将确保在启动时调用每个切片缩减器,从而整齐地初始化整个应用程序状态的每个部分。

虽然您可以在函数内部明确检查if(state === undefined) return initialState,但将初始状态声明为state参数的默认值会更短更简单。

总的来说,这不是一种不好的做法,而是使用Redux的最佳做法。请记住,像AirBNB指南这样的风格规则集仅仅是意见,而不是每个人都必须遵守的严格规则。

有关Redux状态初始化如何工作的详细信息,请参阅Redux文档的Structuring Reducers - Initializing State部分。