Angular和Redux:分派由一个用户交互触发的两个操作(一个同步,一个异步)是否正确?

Angular和Redux:分派由一个用户交互触发的两个操作(一个同步,一个异步)是否正确?,angular,redux,ngrx,Angular,Redux,Ngrx,关于Angular 4和ngrx store中实现的Redux应用程序中的操作流,我有一个一般性问题 基于一篇优秀的帖子: 有一个角度组件-它包含的容器组件行为。它引用了用于加载数据的服务 组件加载数据。一旦数据到达,就会有一个操作被发送到存储在服务页面中。 已订阅组件以存储以下项目: 组成部分: 以及服务: @Injectable() export class RestClient { constructor(private http: HttpClient, private st

关于Angular 4和ngrx store中实现的Redux应用程序中的操作流,我有一个一般性问题

基于一篇优秀的帖子:

有一个角度组件-它包含的容器组件行为。它引用了用于加载数据的服务

组件加载数据。一旦数据到达,就会有一个操作被发送到存储在服务页面中。 已订阅组件以存储以下项目:

组成部分:

以及服务:

@Injectable()
export class RestClient {

    constructor(private http: HttpClient, private store: Store) {}

    public loadItems(pageInfo: PageInfo): void {
        this.http.get('items', {params: {page: pageInfo.page, itemsPerPage: page.size}})
            .map(payload => ({
                type: 'PAGE_LOADED',
                payload: payload
            }))
            .subscribe(action => this.store.dispatch(action));
    }
}
该组件有一个子组件-分页表示组件不包含使用Angular@Output和EventEmitter更改其页面的行为或对其引导实现的存储的引用。父组件实现onPageChangedpageInfo函数,该函数接收子组件发出的页面更改事件

现在的问题或困惑是: 在页面更改时,必须将新值分派到存储,并加载新数据

在onPageChange功能中应该做什么:

onPageChanged(pageInfo: PageInfo) {
        this.store.dispatch({action: 'PAGE_CHANGED', payload: pageInfo});
        this.client.loadList(pageInfo); // load next page
    }
分页已更改,因此将一个操作分派到存储区:PAGE\u已更改 使用PageInfo-当前页面a和页面大小 必须加载下一页:所以下一步是为下一页调用RestClient服务:this.client.loadListpageInfo; 这个调用反过来异步地分派一个新的操作,该操作将加载下一页。 总之,UI中的页面更改会发出两个动作: -换页 -已加载页面

onPageChange action上调度了两个操作是否正确? 在某种意义上,这两者是否应该联系在一起:

store.select('pageInfo')
    .subscribe(pageInfo => this.client.loadList(pageInfo));

或者有其他更好的解决方案吗?

我的解决方案与bryan60建议的一样,使用ngrx效果库:

onPageChanged(pageInfo: PageInfo) {
    this.store.dispatch({action: 'PAGE_CHANGED', payload: pageInfo});
}
onPageChange调度已更改的操作页面,该页面使用新的分页信息更新存储

注册了一个副作用,即在页面上加载一个新页面,并异步触发加载成功或加载错误:

Rest客户端不再分派操作:

@Injectable()
export class RestClient {

    constructor(private http: HttpClient, private store: Store) {}

    public loadItems(pageInfo: PageInfo): Observable {
        return this.http.get('items', {params: {page: pageInfo.page, itemsPerPage: page.size}});
    }
}
在app.module.ts中注册效果:


不,永远不要这样做。存储结果不应触发操作,这会破坏单向信息流。这会产生几乎不可能发现的bug,甚至可能在应用程序中导致非常奇怪的无限循环。如果你看了Redux在Facebook上的最初演示,他们会谈论像这样的事情正是Redux想要解决的。当你这样做的时候,你正在产生一种副作用,而这正是你不应该做的。首先,感谢您阅读了这么长的问题:我认为这是一个非常常见的场景:用户操作导致一个操作被分派到存储更新,并且必须加载新数据,这反过来导致存储更新。有没有一种没有ngrx效果的解决方法,一种通用的重排方法?为什么你不想使用?它适用于像您这样的常见情况。一旦我了解了如何正确使用它,我可能会使用它:我只是想知道ngrx效果背后是什么,如果在clean Redux架构中有类似的方法的话。如果有使用ngrx效果的解决方案,请将其作为答案发布;没有NGRX的方法是将它们视为两个完全分离的动作。页面被更改,这会导致两个不同的状态更改,它们自己的不同负载完全描述了单个状态更改。操作1立即产生所需的任何即时UI效果,例如显示加载图标或其他内容。然后,在检索到描述更新数据并关闭加载图标的状态更改所需的数据后,将调度action 2 async。ngrx/效果有助于使这些动作之间的桥梁更加清晰,事件顺序更加直观。
@Effect() changePage$ = this.actions$
    .ofType(applications.CHANGE_PAGE)
    .switchMap(action => this.client.loadItems(page, itemsPerPage)
        .map(payload => (new applications.LoadSuccessAction(payload)))
        // If request fails, dispatch failed action
        .catch(error => Observable.of(new applications.LoadErrorAction(error)))
    );
@Injectable()
export class RestClient {

    constructor(private http: HttpClient, private store: Store) {}

    public loadItems(pageInfo: PageInfo): Observable {
        return this.http.get('items', {params: {page: pageInfo.page, itemsPerPage: page.size}});
    }
}
@NgModule({
    imports: [
       ...        
       EffectsModule.run(ApplicationEffects),
       ...