简体   繁体   English

当ngrx中的状态更改时调用组件逻辑

[英]Call component logic when state changes in ngrx

I'm currently developing an application with Angular using redux principle with ngrx. 我目前正在使用Redux原理和ngrx使用Angular开发应用程序。

I'm looking for a best practice for reacting to state changes and call some component logic depending on this state. 我正在寻找一种对状态变化做出反应并根据此状态调用一些组件逻辑的最佳实践。 I'll give you an (simplified) example to make clear what I mean: 我将给您一个(简化的)示例以阐明我的意思:

reducers.ts reducers.ts

import {createSelector} from 'reselect';

export const getViewTypeOrFilterChanged = createSelector(isLoading, getActiveViewType, getActiveFilter, (isLoading, activeViewType, activeFilter) => {
    // ensure that data is loaded
    if (!isLoading) {
        return {
            activeViewType: activeViewType,
            activeFilter: activeFilter
        };
    }
});

example-component.ts 例如-component.ts

@Component({ ... })
export class ExampleComponent implements OnInit {

    // properties ...

    constructor(private store: Store<fromRoot.AppState>) {
    }

    ngOnInit() {
        this.subscriptions.push(
            this.store.select(fromRoot.getViewTypeOrFilterChanged).subscribe((result) => {
                if (result) {
                    this.property1 = result.activeType;
                    this.dependentHelperClass.method1(result.activeFilter);

                    this.method1();
                    this.method2(result.activeFilter);
                    this.method3();
                }
            })
        );
    }

    ngOnDestroy() {
        this.subscriptions.forEach((subscription: Subscription) => {
            subscription.unsubscribe();
        });
    }

    // methods ...
}

As you can see I'm also using reselct to combine three different slices of state within a selector (getViewTypeOrFilterChanged). 如您所见,我还在使用reselct在选择器(getViewTypeOrFilterChanged)中组合三个不同的状态片。 In the subscription to this selector I then want to take some actions according to the combined state. 然后,在对该选择器的订阅中,我想根据组合状态采取一些措施。

The thing is, I'm feeling like using ngrx store and subscriptions more in a way of publish/subscribe pattern here and it feels not quite correct. 事情是,我觉得这里更喜欢使用ngrx存储和订阅以一种发布/订阅模式的方式,感觉不太正确。 Also the subscriptions (I have multiple ones) in ngOnInit and unsubscriptions in ngOnDestroy bother me, but I can't think of a way achieving the same results using eg async pipe. ngOnInit中的订阅(我有多个订阅)和ngOnDestroy中的取消订阅也让我感到困扰,但是我想不出一种使用例如异步管道来达到相同结果的方法。 Is there maybe a more elegant way of reacting to (combined) state changes? 是否有一种更优雅的方式来对(组合)状态变化做出反应?

Thanks! 谢谢!

With RxJS you should think of everything as a stream - the following code is just as an example, because I don't really know any of your UI-logic so just look at the structure and not at the logic of the code, since it's more like a very wild guess of mine: 使用RxJS时,您应该将所有内容视为流-以下代码仅作为示例,因为我并不真正了解您的UI逻辑,因此只需查看结构而不是代码的逻辑,因为它是更像是我的一个非常疯狂的猜测:

@Component({ ... })
export class ExampleComponent implements OnInit {
    private destroyed$ = new Subject<boolean>();

    // the following streams can be used in the controller
    // as well as in the template via | async
    // the .share() is just so the | async pipe won't cause unneccessary stream-creations (the result should be the same regardless of the .share(), it's just a minor performance-enhancement when using multiple | async)
    isLoading$ = this.store.select(fromRoot.isLoading).share();
    activeViewType$ = this.store.select(fromRoot.getActiveViewType).share();
    activeFilter$ = this.store.select(fromRoot.getActiveFilter).share();
    activeViewTypeAndFilter$ = Observable.combineLatest(this.activeViewType$, this.activeFilter$).share();

    constructor(private store: Store<fromRoot.AppState>) {
    }

    ngOnInit() {
        this.isLoading$
            .filter(isLoading => !isLoading) // the initial stream will not emit anything until "loading" was false once
            .switchMapTo(this.activeViewTypeAndFilter$)
            .do([viewType, filter] => {
                this.dependentHelperClass.method1(activeFilter);

                this.method1();
                this.method2(activeFilter);
                this.method3();
            })
            .takeUntil(this.destroyed$)  //this stream will automatically be unsubscribed when the destroyed$-subject "triggers"
            .subscribe();
    }

    ngOnDestroy() {
        this.destroyed$.next(true);
        this.destroyed$.complete();
    }

    // methods ...
}

As I said: logic-wise I cannot say if this is what you need, but that's just a question of using different operators and/or a different order to arrange your "main-stream" differntly. 正如我所说:从逻辑上讲,我不能说这是否是您所需要的,但这只是使用不同的运算符和/或不同的顺序来不同地排列“主流”的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM