2

当我们初始化我们的 Store 时:

StoreModule.provideStore({r1: Reducer1, r2: Reducer2, ...})

我们确实将 reducer 传递给 Store 进行存储。但是我们从来没有真正将初始状态传递给存储,除了在 r​​educers 函数中定义它:

const someReducer = (state = initialState, act: Action) => { ... }

那么,是不是在应用程序启动时,所有的 reducer 都被调用一次,从 reducer 定义中获取初始状态,然后将状态存储在 NgRx Store 中?如果是这样,是不是每个reducer都必须有一个初始状态值?否则状态将始终未定义?

而且,如果所有 reducer 都在 bootstrap 中调用,NgRx 如何确保 reduce 必须达到默认情况?:

case ...:
   ...
default:
   return initialState

非常感谢!任何帮助表示赞赏!

4

1 回答 1

7

每次将 action 发送到 store 时,都会调用每个已注册的 reducer。reducer 只是一个函数,它接受当前状态加上一个动作并返回一个新状态。

所以是的,在引导时会调度一个 init-action(因此每个 reducer 都会被调用)。例如,如果您使用store-devtools,您将看到调用了初始操作@ngrx/store/init。由于此时当前状态未定义,因此使用以下内容调用 reducer 函数: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-function有一个带默认值的参数(initialstate)时,store就会用这个初始状态初始化。如果你没有为 reducer 定义一个默认值,那部分状态将保持undefined. 这可能是一个有效的场景。例如,考虑一个处理管理部分操作的化简器。除非具有提升权限的用户使用您的应用程序,否则您可能不希望在该状态片中有任何内容。

现在到了我认为您的问题来自的地步:

您不想initialState在默认情况下返回!由于每个 reducer 都会在每个 action-dispatch 上被调用,所以默认情况应该是return state. 商店不知道一个动作的减速器是什么意思。它用当前状态和分派的动作调用每个reducer,并期望得到一个(新的)状态。
某个 reducer 是否应该对某个动作做出反应取决于您。不应对此操作做出反应的所有其他减速器都应返回其未更改状态(通过 default 案例)。当然,您可以让多个减速器对同一个动作做出反应!

在您的情况下,如果每个减速器initialState在默认情况下返回,您的整个应用程序状态将重置为其初始状态,但对调度操作做出反应的减速器除外。

TL;DR 对于您的问题:

  • 是的,所有 reducer 函数都会在引导程序(以及所有其他动作调度)上调用......
  • ...是的,那是商店使用初始状态初始化的时候。
  • 不,reducer 不一定总是有初始状态*
  • 如果一个状态切片最初是undefined,它仍然可以通过reducer 通过返回一个新状态来响应一个动作来改变。
  • 每个对动作没有反应的 reducer 都应该通过default-case 返回当前状态。

* 当然,这仅在您的应用程序的其余部分能够处理未定义状态时才有意义

于 2017-05-06T22:24:51.227 回答