我有一个动作/减速器/组件.在我的一个组件(组件转储)中,我有一个Select.我得到有关我的商店的过滤器类型的信息.我在哪里可以处理它或减速机?
IMO,对数据进行排序的正确位置不是直接在Reducer中,而是在选择器中.
来自redux docs:
计算派生数据
Reselect是一个用于创建memoized,可组合选择器函数的简单库.重选选择器可用于有效地计算Redux存储中的派生数据.
我目前正在使用选择器来过滤和排序数据.
该州没有数据重复.您不必存储按特定方式排序的项目副本.
可以在不同的组件中使用相同的数据,每个组件使用不同的选择器功能来进行排序.
您可以使用应用程序中已有的选择器组合选择器应用许多数据计算.
如果你做得对,你的选择器将是纯函数,那么你可以轻松地测试它们.
在许多组件中使用相同的选择器.
您可以在使用Redux存储的@connect -ing React组件时对数据进行排序:
function mapStateToProps(state) { var items = state.items.slice(0); items.sort() return { items: items } } @connect(mapStoreToProps) class MyComponent extends React.Component { render() { var items = this.props.items; } }
Redux文档在Todo示例中显示了类似的案例:http://rackt.org/redux/docs/basics/UsageWithReact.html
我在Redux Store中保存了items,sortKey和sortKind(asc/desc).
在我的Angular组件中(我相信React会相同),我将商店状态作为Observable获取,以便我可以在UX中显示items,sortKey和sortOrder.
当用户单击表列以更改排序键(顺序)时,我将新键/排序顺序分配给该状态的reducer.
然后,reducer执行新的排序,并返回具有更新值的新状态.
因此,组件中的Observable引发了更新UX的事件.
优点:
将分类逻辑排除在组件之外
通过在该状态下保存sortKey和sortKind,如果用户刷新浏览器,您可以精确地恢复UX(我使用Redux-LocalStorage进行同步)
由于商店具有已排序的商品,因此您只会在用户主动要求时执行排序.
当用户可能返回到组件时,会记住已排序的项目.
我的reducer("bizzes"是我的项目列表,我使用Immutable.List来存储项目)
import { List } from 'immutable'; import { IBizz, IBizzState } from './bizz.types'; import { BIZZES_SET, BIZZES_SORT} from 'store/constants'; const SORT_ASC = 'asc'; const SORT_DESC = 'desc'; const defaultSortKey = 'serialNo'; const defaultSortOrder = SORT_ASC; const INITIAL_STATE: IBizzState = { bizzes: List([]), sortKey: defaultSortKey, sortOrder: defaultSortOrder }; export function bizzReducer(state: IBizzState = INITIAL_STATE, action: any): IBizzState { switch (action.type) { case BIZZES_SET: return { bizzes: List(action.payload.bizzes), sortKey: action.payload.sortKey || defaultSortKey, sortOrder: action.payload.sortOrder || defaultSortOrder }; case BIZZES_SORT: let sortKey = action.payload.sortKey || defaultSortKey; if(sortKey === state.sortKey) { state.sortOrder = state.sortOrder === SORT_ASC ? SORT_DESC : SORT_ASC; } return { bizzes: List(state.bizzes.sort( (a, b) => { if( a[sortKey] < b[sortKey] ) return state.sortOrder === SORT_ASC ? -1 : 1; if( a[sortKey] > b[sortKey] ) return state.sortOrder === SORT_ASC ? 1: -1; return 0; })), sortKey: sortKey, sortOrder: state.sortOrder }; default: return state; } }
和我的组件(我使用Ng2-Redux将商店作为Observables):
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy } from '@angular/core'; import { select } from 'store'; import { BizzActions } from 'actions/index'; @Component({ selector: 'bizzlist', templateUrl: './bizz-list.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class BizzListComponent implements OnInit { @select([ 'bizzState']) bizzState$; public sortOrder: string; public sortKey: string; public bizzes = []; private bizzStateSubscription; constructor( public bizzActions: BizzActions ) { } ngOnInit() { this.bizzStateSubscription = this.bizzState$.subscribe( bizzState => { this.bizzes = bizzState.bizzes; this.sortKey = bizzState.sortKey; this.sortOrder = bizzState.sortOrder; }); } ngOnDestroy() { this.bizzStateSubscription.unsubscribe(); } public sortBizzes(key) { this.bizzActions.sortBizzes(key); } }
如您所见,我正在使用Action(称为BizzActions)来执行实际的Redux调度.您可以在组件中执行此操作,但我更愿意将这些内容分开.好的方法,这是我的BizzActions(服务):
import { Injectable } from '@angular/core'; import { NgRedux, IAppState } from 'store'; import { BIZZES_SET, BIZZES_SORT } from 'store/constants'; @Injectable() export class BizzActions { constructor (private ngRedux: NgRedux) {} public setBizzes = (bizzes: any) => { return this.ngRedux.dispatch({ type: BIZZES_SET, payload: { bizzes: bizzes } }); }; public sortBizzes = (key:string) => { return this.ngRedux.dispatch({ type: BIZZES_SORT, payload: { sortKey: key } }); }; }