使用 Angular2 ngrx 的类似 Twitter 的应用程序。构建 AppState

Twitter-like app with Angular2 ngrx. Structuring AppState

我最近一直在研究 ngrx 和 redux 模式,并且正在考虑如何将现有的 Angular2 应用重写为使用 ngrx/store。 我拥有的是一个应用程序,用户可以在其中查看并且(如果登录)可以点赞和发布引文。 典型的引用对象如下所示:

{ text: "Success is the ability to go from one failure to another with no loss of enthusiasm.", publisher: user12345, rank: 14, //some more data }

应用程序结构如下所示:

因此,我对 AppState 树的外观感到非常沮丧。

AppState {
    UserState {
        UserCitationsState, 
        UserInfoState, 
        AuthState
    },
    RouterState,
    UserPageState //State representing the other user's page viewed
    //etc
}

主要问题是 - 我应该在每个状态中存储什么,因为所有数据都是根据请求从后端 REST api 获取的。它是否只是布尔值,例如:

UserPageState {
    loading: false,
    loaded: true
}

还是它也应该存储所有信息并在每次请求新用户页面时替换它?每次用户导航到其他用户页面时,所有数据都是从后端获取的。 这就是我最基本的困惑所在——如何使用 redux 处理这类应用程序。

编辑 目前我将自己限制在 5 个状态(5 个减速器)来代表整个应用程序:

  1. AuthState
  2. 用户状态
  3. 用户列表状态
  4. 引用状态
  5. 引文列表状态

但是,在整个应用程序状态下,我复制了其中的许多内容。我想这很好。或者有更好的方法吗?

export interface AppState
{
  localUser: AuthState
  
  //homePage
    homeCitation: CitationState

  //profilePage
    profileInfo: UserState
    profileCitations: CitationListState
    favouriteCitations: CitationListState
    subscribers: UserListState

  //userPage (when local user navigates to citation publisher's profile)
    userInfo: UserState
    userCitations: CitationListState
    userSubscribers: UserListState
  
  //feedPage
    feed: CitationListState
  
  //.....
}

我最初的想法是将应用程序状态视为数据库。

我会使用以下减速器构建:

AppState: {
   CitationState
   UserProfileState,
   UserInfo,
   RouterState
}

interface CitationState {
 citations: Citation[]
}

interface UserProfileState { 
 userProfiles: UserProfile[]
}

interface UserInfo { 
 userInfo: UserInfo
}

interface Citation {
  id: number;
  publisherId (userId): number;
  rank: number;
  text: string;
}

interface UserProfile {
  userId: number;
  citationIds: number[]
}

interface UserInfo {
   userId: number;
   authToken: string;
}

然后每个智能组件都会根据需要组合数据以呈现视图。例如,您可以通过检查路由的用户配置文件是否与 UserInfo reducer 中的匹配来确定用户配置文件是否是您自己的。

不要担心在状态中创建 loading/loading,这是您可以从商店状态中得出的东西。由于所有数据都是可观察的,因此当您从中查询时,您将获得可用数据的最新快照。

加载用户的引文时,不是绑定到商店的加载 属性,而是为该数据构建查询。

例如:

let userCitation$ = state.select(appState => appState.citations)
     .map(citations => {
           let userCitation = citations.find(c => c.id === userId);
           return {
              loaded: !!userCitation,
              userCitation: userCitation
           };
     });