如何重置 ngrx 9 的整个商店?
how to reset whole store of ngrx 9?
我已经看到了同样的问题 但是因为我使用 ngrx9 我认为应该有稍微不同的解决方案。我的应用程序模块中的代码和 reducer 如下所示
.....
StoreModule.forRoot(
reducers,
{
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
...
而我的进口减速机是
export const reducers: ActionReducerMap<AppState> = {
[friendsReducer.friendsFeatureKey]: friendsReducer.reducer,
[authReducer.authFeatureKey]: authReducer.reducer,
...
};
export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [] : [];
我的 LOGOUT
操作存储在 auth.actions
中。
那么我应该如何包含 root reducer 来重置所有状态?
只需添加 MetaReducer 即可清除您的状态
export function clearOnLogoutMetaReducer(reducer) {
return function(state, action) {
if(action.type === logout.type) {
return reducer(undefined, action);
}
return reducer(state, action);
}
}
并将其添加到您的 metareducers 数组
接受的答案是我在 Whosebug 上经常看到的建议,不幸的是,这是你永远不应该做的事情。
问题
如果您使状态可能未定义,您将 运行 遇到几个问题:
您连接到商店的任何东西(通常只是选择器)都必须以考虑潜在未定义值的方式编写。这会很快变得丑陋,如果犯了错误,可能会导致难以发现错误。
Javascript 如果引擎操纵的对象具有相同的“形状”,则它们的性能会更好。这个主题很复杂,但基本思想是如果对象具有相同的形状,编译器可以使用内联缓存优化操作(这里有一篇关于这个主题的更详细的文章:https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html)。如果您只是通过将其设置为未定义来重置状态,那么状态对象会改变形状,并且您会损失一些性能。在大多数应用程序中,这可能不会产生明显的影响,但需要注意这一点。
你打破了 redux 设计模式的基本原则之一,即你应该维护一个具有一致接口的集中式状态存储。 redux 设计模式的卖点之一是,如果你遵循它,你就会知道你的应用程序状态将始终具有一致的接口,你永远不必担心状态的某些部分不存在,并且可能导致的问题。这就是为什么 reducer 总是从初始状态对象创建,并且状态属性是在加载其提供程序时急切创建的,而不是动态添加到状态的。如果通过将状态设置为未定义来重置状态,则会失去此保证以及 redux 的一大块价值。
解决方案
要清除商店,您需要分派一个减少为新的初始状态对象的操作。 ngrx/redux 的一大优点是,操作是沿着单个流分派的。这意味着一个特征存储中的缩减器(在你的例子中 'friends')可以监听另一个存储中的动作(在你的例子中 'auth')。因此,在您的 friends.reducer.ts 中执行以下操作:
import * as AuthActions from 'wherever/your/auth/actions/are';
// Replace this with actual interface
export interface FriendsState {
friends: string[];
}
// Replace this with actual object
export const initialFriendsState:FriendsState = {
friends: [],
}
export const reducer = createReducer(
initialFriendsState,
on(AuthActions.LOGOUT, (state: FriendsState) => ({...initialFriendsState})),
on(FriendsActions.GET_FRIENDS (state: FriendsState, {friends}) => ({...state, friends})
//...whatever other reducers you have in your friends store
);
我已经看到了同样的问题
.....
StoreModule.forRoot(
reducers,
{
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
...
而我的进口减速机是
export const reducers: ActionReducerMap<AppState> = {
[friendsReducer.friendsFeatureKey]: friendsReducer.reducer,
[authReducer.authFeatureKey]: authReducer.reducer,
...
};
export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [] : [];
我的 LOGOUT
操作存储在 auth.actions
中。
那么我应该如何包含 root reducer 来重置所有状态?
只需添加 MetaReducer 即可清除您的状态
export function clearOnLogoutMetaReducer(reducer) {
return function(state, action) {
if(action.type === logout.type) {
return reducer(undefined, action);
}
return reducer(state, action);
}
}
并将其添加到您的 metareducers 数组
接受的答案是我在 Whosebug 上经常看到的建议,不幸的是,这是你永远不应该做的事情。
问题
如果您使状态可能未定义,您将 运行 遇到几个问题:
您连接到商店的任何东西(通常只是选择器)都必须以考虑潜在未定义值的方式编写。这会很快变得丑陋,如果犯了错误,可能会导致难以发现错误。
Javascript 如果引擎操纵的对象具有相同的“形状”,则它们的性能会更好。这个主题很复杂,但基本思想是如果对象具有相同的形状,编译器可以使用内联缓存优化操作(这里有一篇关于这个主题的更详细的文章:https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html)。如果您只是通过将其设置为未定义来重置状态,那么状态对象会改变形状,并且您会损失一些性能。在大多数应用程序中,这可能不会产生明显的影响,但需要注意这一点。
你打破了 redux 设计模式的基本原则之一,即你应该维护一个具有一致接口的集中式状态存储。 redux 设计模式的卖点之一是,如果你遵循它,你就会知道你的应用程序状态将始终具有一致的接口,你永远不必担心状态的某些部分不存在,并且可能导致的问题。这就是为什么 reducer 总是从初始状态对象创建,并且状态属性是在加载其提供程序时急切创建的,而不是动态添加到状态的。如果通过将状态设置为未定义来重置状态,则会失去此保证以及 redux 的一大块价值。
解决方案
要清除商店,您需要分派一个减少为新的初始状态对象的操作。 ngrx/redux 的一大优点是,操作是沿着单个流分派的。这意味着一个特征存储中的缩减器(在你的例子中 'friends')可以监听另一个存储中的动作(在你的例子中 'auth')。因此,在您的 friends.reducer.ts 中执行以下操作:
import * as AuthActions from 'wherever/your/auth/actions/are';
// Replace this with actual interface
export interface FriendsState {
friends: string[];
}
// Replace this with actual object
export const initialFriendsState:FriendsState = {
friends: [],
}
export const reducer = createReducer(
initialFriendsState,
on(AuthActions.LOGOUT, (state: FriendsState) => ({...initialFriendsState})),
on(FriendsActions.GET_FRIENDS (state: FriendsState, {friends}) => ({...state, friends})
//...whatever other reducers you have in your friends store
);