如何在ngrx中将withLatestFrom与选择器一起使用? [英] How to use withLatestFrom with a selector in ngrx?

查看:91
本文介绍了如何在ngrx中将withLatestFrom与选择器一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有ngrx应用程序,但我无法通过组件中发送的有效负载从选择器中获取值.

I have ngrx application, and I can't get the value from a selector in the effect, by the payload I sent in the component.

我写了一个处理代码的例子:

I write an example code of what I deal with:

这是我的状态,其中是一个简单的docs数组.

This is my state, a simple docs array in it.

export const initialState = {
  docs: [{ id: 1, name: "doc1" }, { id: 2, name: "doc2" }]
};

export const reducer = createReducer(
  initialState,
);

对于这个问题,我不采取任何行动,这不是问题.

I dont handle any action for this questions, this is not the issue.

在我的组件中,使用选择器获取数组:

In my component I get the array using a selector:

docs$ = this.store.pipe(select(fromStore.getAllDocs));

{{docs$ | async | json}}

减速器

export const selectDocsState = createFeatureSelector("docs");

export const selectDocsStatusState = createSelector(
  selectDocsState,
  state => state["docs"]
);

export const getAllDocs = createSelector(
  selectDocsStatusState,
  getDocs
)

我还有一个选择器,可通过id获取:

I also have a selector to get by id:

{{docsById$ | async | json }}

docsById$ = this.store.pipe(select(fromStore.getById, { id: 1 }));

在减速器中:

export const getById = createSelector(
  selectDocsStatusState,
  getDocs,
  (state, docs, props) => {
    console.log({ props });
    return docs.docs.docs.filter(d => d.id === props.id);
  }
)

到目前为止,一切都很好.我得到了docs数组并显示它.

So far everything good. I get the docs array and display it.

现在,在我的组件中,我调度一些动作并按效果捕获:

Now, in my component I dispatch some action and catch by effect:

this.store.dispatch({ type: 'GET_DOC', payload: { id: 2 } });

实际上,我想知道此ID是否在商店中.

And in the effect I want to know if this id is in the store or not.

所以我将rxjs中的withLatestFrom与getById选择器一起使用.

So I use withLatestFrom from rxjs with the getById selector.

withLatestFrom((a: any) =>
  this.store.pipe(select(fromDocs.getById, { id: a.payload.id }))
),

问题是我没有从选择器中获取值,而是得到了存储实例.

The problem is i'm not getting the value from the selector instend I get the store instance.

tap(v => {
  console.log({ v });
}),

完整效果:

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 });
      })
    )
  );

这是我在stackbliz中的完整示例. /a>

Here is my full example in stackbliz.

我在这里想念什么?

推荐答案

NgRx Docs-Incorporating State ,但我发现了布兰登·罗伯茨(Brandon Roberts)github评论更有用:

This is covered in the NgRx Docs - Incorporating State but I found Brandon Roberts github comment more useful:

使用ofType运算符后,在听操作时,有两项主要操作:

There are two predominant things you do when listening to an action after using the ofType operator:

actions.pipe(
  ofType('SOME_ACTION')
  someMap(action => doSomething(action))
)

actions.pipe(
  ofType('SOME_ACTION'),
  withLatestFrom(store.select(someThing)),
  someMap(([action, latest]) => doSomething(action, latest))
)

就效果而言,它们有两种不同的行为.第一个在分派动作之前什么也不做,这是应该做的.

These have two different behaviors as far as effects are concerned. The first one doesn't do anything until the action is dispatched, which is what it should do.

第二个立即订阅withLatestFrom,无论是否已分派动作.如果选择器使用的状态尚未初始化,则可能会收到意想不到的错误.为了使其懒惰",您最终不得不将其嵌套在一个扁平化的可观察运算符中.

The second one immediately subscribes to the withLatestFrom whether the action is dispatched yet or not. If that state used by the selector is not initialized yet, you could get an error you're not expecting. In order to make it "lazy" you end up having to nest it within a flattening observable operator.

actions.pipe(
  ofType('SOME_ACTION'),
  someMap(action =>
    of(action).pipe(
      withLatestFrom(store.select(someThing)),
      someMap(([action, latest]) => doSomething(action, latest))
    )
)


应用此操作可获得以下信息:


Applying this gives the following:

  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();
          })
        )
      )
    );
  });

这篇关于如何在ngrx中将withLatestFrom与选择器一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆