2016-09-19 23 views
16

tôi cập nhật @ngrx/effects từ 1.x để 2.xLàm cách nào để truy cập cây trạng thái có hiệu lực? (@ Ngrx/hiệu ứng 2.x)

Trong 1.x tôi có quyền truy cập của cây nhà nước có hiệu lực:

constructor(private updates$: StateUpdates<AppState>) {} 

    @Effect() bar$ = this.updates$ 
    .whenAction(Actions.FOO) 
    .map(obj => obj.state.user.isCool) 
    .distinctUntilChanged() 
    .filter(x => x) 
    .map(() => ({ type: Actions.BAR })); 

Bây giờ trong 2 .x, nó chỉ cho tôi hành động. Vẫn còn một cách để tiếp cận cây trạng thái? Hoặc tôi nên tránh sử dụng như thế này bởi vì nó không phải là một thực hành tốt?

constructor(private actions$: Actions) {} 

    @Effect() bar$ = this.actions$ 
    .ofType(ActionTypes.FOO) 
    .map((obj: any) => { 
     console.log(obj);    // here is action only 
     return obj.state.user.isCool // so it is wrong here 
    }) 
    .distinctUntilChanged() 
    .filter(x => x) 
    .map(() => ({ type: ActionTypes.BAR })); 

Trả lời

19

Một cách khác là sử dụng .withLatestFrom(this.store). Vì vậy, mã hoàn chỉnh là:

constructor(
    private actions$: Actions, 
    private store: Store<AppState> 
) {} 

@Effect() bar$ = this.actions$ 
    .ofType(ActionTypes.FOO) 
    .withLatestFrom(this.store, (action, state) => state.user.isCool) 
    .distinctUntilChanged() 
    .filter(x => x) 
    .map(() => ({ type: ActionTypes.BAR })); 
+1

Ngoài ra, nếu bạn sử dụng 'this.store.select (fromRoot.getUserIsCool)' bạn không phải sử dụng 'distinctUntilChanged()' ... đúng không? – Helzgate

+0

Chuyển cửa hàng sang 'withLatestFrom' ném' TypeError: Bạn đã cung cấp đối tượng không hợp lệ trong đó luồng được mong đợi. Bạn có thể cung cấp một Observable, Promise, Array, hoặc Iterable.'. Nó hoạt động mặc dù. Bất kỳ ý tưởng tại sao tôi nhận được lỗi? –

4

Hiệu ứng không phải là thuộc tính lớp học; chúng cũng có thể là phương pháp. Điều đó có nghĩa là bạn có thể truy cập một cửa hàng được tiêm vào hàm tạo.

Tại thời điểm viết câu trả lời này, ngữ nghĩa của tờ khai tài sản vàpublic/privatethông số nhà xây dựng không rõ ràng với tôi. Nếu các thuộc tính được khai báo sau hàm tạo, chúng có thể truy cập các thành viênpublic/privateđược khai báo thông qua các tham số hàm tạo - do đó bạn không phải khai báo các hiệu ứng của mình dưới dạng hàm.

Với các cửa hàng tiêm, bạn sẽ có thể sử dụng một nhà điều hành như mergeMap để có được nhà nước và kết hợp nó với bản cập nhật mà bạn nhận được:

@Effect() 
bar$(): Observable<Action> { 

    return this.actions$ 
    .ofType(ActionTypes.FOO) 
    .mergeMap((update) => this.store.first().map((state) => ({ state, update }))) 
    .map((both) => { 
     // Do whatever it is you need to do with both.update and both.state. 
     return both.update; 
    }) 
    .distinctUntilChanged() 
    .filter(x => x) 
    .map(() => ({ type: ActionTypes.BAR })); 
    } 
} 

hay không làm điều này là thực hành tốt là một vấn đề của ý kiến, tôi đoán. Đọc trạng thái - lý tưởng bằng cách soạn một bộ chọn kiểu ngrx - âm thanh hợp lý, nhưng nó sẽ sạch hơn nếu tất cả thông tin bạn cần cho một hiệu ứng cụ thể được bao gồm trong hành động mà nó đang nghe.

+0

Tôi đã chỉnh sửa câu trả lời của mình. Tôi đã thử nghiệm những gì tôi đã viết - ra khỏi đỉnh đầu của tôi - và ứng dụng của tôi đã trở nên bối rối, như 'combineLatest' dẫn đến chu kỳ cập nhật trạng thái. Thêm một bình luận lại: thực hành tốt, quá. – cartant

+1

cảm ơn bạn rất nhiều! Lần thử đầu tiên của bạn là đi đúng hướng, cần thay đổi thành 'withLatestFrom ' –

+1

Yep,' withLatestFrom' là một giải pháp tốt hơn nhiều. – cartant

Các vấn đề liên quan