我有 ngrx 应用程序,我无法通过我在组件中发送的有效负载从效果中的选择器中获取值。
我写了一个我处理的示例代码:
这是我的状态,里面有一个简单的 docs 数组。
export const initialState = {
docs: [{ id: 1, name: "doc1" }, { id: 2, name: "doc2" }]
};
export const reducer = createReducer(
initialState,
);
Run Code Online (Sandbox Code Playgroud)
我不处理这个问题的任何行动,这不是问题。
在我的组件中,我使用选择器获取数组:
docs$ = this.store.pipe(select(fromStore.getAllDocs));
{{docs$ | async | json}}
Run Code Online (Sandbox Code Playgroud)
减速机:
export const selectDocsState = createFeatureSelector("docs");
export const selectDocsStatusState = createSelector(
selectDocsState,
state => state["docs"]
);
export const getAllDocs = createSelector(
selectDocsStatusState,
getDocs
)
Run Code Online (Sandbox Code Playgroud)
我还有一个通过 id 获取的选择器:
{{docsById$ | async | json }}
docsById$ = this.store.pipe(select(fromStore.getById, { id: 1 }));
Run Code Online (Sandbox Code Playgroud)
在减速器中:
export const getById = createSelector(
selectDocsStatusState,
getDocs,
(state, docs, props) => {
console.log({ props });
return docs.docs.docs.filter(d => d.id === props.id);
}
)
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都很好。我得到 docs 数组并显示它。
现在,在我的组件中,我分派了一些动作并按效果捕捉:
this.store.dispatch({ type: 'GET_DOC', payload: { id: 2 } });
Run Code Online (Sandbox Code Playgroud)
结果我想知道这个 id 是否在商店里。
所以我使用withLatestFromfrom rxjs 和 getById 选择器。
withLatestFrom((a: any) =>
this.store.pipe(select(fromDocs.getById, { id: a.payload.id }))
),
Run Code Online (Sandbox Code Playgroud)
问题是我没有从选择器那里得到值,我得到了商店实例。
tap(v => {
console.log({ v });
}),
Run Code Online (Sandbox Code Playgroud)
完整效果:
getDoc$ = createEffect(() =>
this.actions$.pipe(
ofType("GET_DOC"),
map(a => a),
tap(a => {
console.log({ a });
}),
withLatestFrom((a: any) =>
this.store.pipe(select(fromDocs.getById, { id: a.payload.id }))
),
tap(v => {
console.log({ v }); // <--------------- HERE SHOULD BE THE DOC AND THE ACTION.PAYLOAD, v[0].a.payload, v[1].id
}),
exhaustMap(payload => {
return of({ type: "SOME_ACTION", payload: null });
})
)
);
Run Code Online (Sandbox Code Playgroud)
我在这里想念什么?
And*_*len 13
这在NgRx Docs - Incorporating State 中有介绍,但我发现Brandon Roberts github 评论更有用:
使用 ofType 运算符后,在监听动作时,您主要做两件事:
Run Code Online (Sandbox Code Playgroud)actions.pipe( ofType('SOME_ACTION') someMap(action => doSomething(action)) )和
Run Code Online (Sandbox Code Playgroud)actions.pipe( ofType('SOME_ACTION'), withLatestFrom(store.select(someThing)), someMap(([action, latest]) => doSomething(action, latest)) )就效果而言,它们有两种不同的行为。第一个在动作被调度之前不做任何事情,这是它应该做的。
第二个立即订阅 withLatestFrom ,无论该操作是否已调度。如果选择器使用的那个状态还没有初始化,你可能会得到一个你意想不到的错误。为了让它“懒惰”,你最终不得不将它嵌套在一个扁平化的可观察操作符中。
Run Code Online (Sandbox Code Playgroud)actions.pipe( ofType('SOME_ACTION'), someMap(action => of(action).pipe( withLatestFrom(store.select(someThing)), someMap(([action, latest]) => doSomething(action, latest)) ) )
应用它给出以下内容:
getDoc$ = createEffect(() => {
return this.actions$.pipe(
ofType(fromDocs.getDocument),
switchMap(action =>
of(action).pipe(
withLatestFrom(
this.store.select(fromDocs.getById, { id: action.payload.id })
),
map(([action, latest]) => {
return fromDocs.someAction();
})
)
)
);
});
Run Code Online (Sandbox Code Playgroud)
使用 Ngrx 中的 concatLatestFrom(withLatestFrom 的惰性版本)来缓解原始状态在需要之前尚未启动的情况。
import {Actions, concatLatestFrom, createEffect, ofType} from '@ngrx/effects';
concatLatestFrom(() => this.store.select(fromDocs.getById, { id: action.payload.id }),
map(([action, latest]) => {
return fromDocs.someAction();
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7361 次 |
| 最近记录: |