在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是一个糟糕的设计决策。
答案 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部分。