【问题标题】:Twitter-like app with Angular2 ngrx. Structuring AppState带有 Angular2 ngrx 的类似 Twitter 的应用程序。构建 AppState
【发布时间】:2016-12-15 18:49:13
【问题描述】:

我最近一直在研究 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 个 reducer)来代表整个应用程序:

  1. 身份验证状态
  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
  
  //.....
}

【问题讨论】:

    标签: rest angular routing redux ngrx


    【解决方案1】:

    我最初的想法是把应用程序的状态想象成数据库。

    我会使用以下 reducer 构建结构:

    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 中的匹配来确定用户配置文件是否是您自己的。

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

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

    例如:

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

    【讨论】:

    • 你能看看我所做的编辑吗?你对这样的结构有什么看法?因为目前我只能将我的应用程序状态想象为每页。
    • 这取决于每个状态的内容。例如,homeCitation(主页)中包含哪些数据?对我来说,您似乎应该尝试对数据进行一些概括。与其思考,该页面需要这些数据并将其放置在页面缩减器中,不如考虑如何将这些数据放在其他页面可以使用的地方。 除非,您有要保存的特定属性我不会制作reducers-to-pages。
    • 我看到了 CitationListState 的多种用途。请记住,如果您在应用程序中的任何地方都有重复的数据,那么您可能做错了。例如,citation 是否可以同时存储在 favouriteCitationsfeed 中?如果答案是肯定的,那么您需要创建一个名为 Citations 的 reducer,并将所有这些都收集在那里。
    • @PeterSmith,你是完全正确的。我的意思是我有一个减速器 - 引文。但是,AppState 包含多个使用 Citations reducer 的子状态。我在这里的一个单独问题中更详细地描述了我的问题:link。如果您能看一下,我将不胜感激。
    猜你喜欢
    • 2012-01-31
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多