每次向商店发送操作时,every调用已注册的减速器。减速器只是一个函数,它接受当前状态加上一个操作并返回一个新状态。
所以是的,在引导时会调度一个 init-action (因此每个减速器都会被调用)。如果你使用商店开发工具 https://github.com/ngrx/store-devtools例如,您将看到初始操作被称为@ngrx/store/init https://github.com/ngrx/store/blob/master/src/dispatcher.ts#L9。
由于此时当前状态未定义,因此将使用以下命令调用减速器函数:someReducer(undefined, { type: '@ngrx/store/init' })
当使用以下参数调用函数时undefined
并且它有一个带有默认值的参数,它将使用该默认值。
function funcWithoutDefault(myParam) {
console.log(myParam);
}
funcWithoutDefault('hello'); // 'hello'
funcWithoutDefault(undefined); // undefined
function funcWithDefault(myParam = 'world') {
console.log(myParam);
}
funcWithDefault('hello'); // 'hello'
funcWithDefault(undefined); // 'world'
这对你来说可能不是什么新鲜事。但希望它有助于回答您有关初始状态的问题:
正如我所说,目前的状态是undefined
在调用 init-action 之前。因此,当reducer函数有一个带有默认值(初始状态)的参数时,存储将使用该初始状态进行初始化。
如果您没有为减速器定义默认值,则状态的切片将保持不变undefined
。
这可能是一个有效的场景。例如,考虑一个处理管理部分操作的减速器。除非具有提升权限的用户使用您的应用程序,否则您可能不希望在该状态片中拥有任何内容。
现在我想你的问题来自于:
你不想退回initialState
在默认情况下!由于每个减速器都会在每次操作调度时被调用,因此默认情况应该return state
。
商店不知道某个操作的减速器的用途。它使用当前状态和分派的操作调用每个减速器,并期望返回一个(新的)状态。
某个减速器是否应对某个操作做出反应取决于您。不应对此操作做出反应的所有其他减速器都应返回其未更改的状态(via the default
case)。当然,您可以让多个减速器对同一操作做出反应!
在你的情况下,如果每个减速器都返回initialState
在默认情况下,您的整个应用程序状态将重置为其初始状态,除了对分派操作做出反应的减速器之外。
TL;DR 对于您的问题:
- 是的,所有减速器函数都会在引导程序(以及所有其他操作调度)上被调用......
- ...是的,那就是商店用初始状态初始化的时候。
- 不,reducer 不一定总是有初始状态*
- 如果状态切片最初是
undefined
,它仍然可以通过减速器通过返回新状态来对操作做出反应来改变。
- 每个对动作没有反应的减速器都应该通过
default
-case.
* of course this only makes sense when the rest of your application is able to handle an undefined state