【问题标题】:Redux: Normalizing Global StateRedux:规范化全局状态
【发布时间】:2016-10-28 05:28:39
【问题描述】:

假设以下情况:

1. Page has many posts
2. Post has many comments

我有以下减速器:

1. PagesReducer
2. PostsReducer
3. PostReducer
4. CommentsReducer

我现在有以下状态:

pagesByTitle: {
  dorrisPage: {
    isFetching: false,
    data: {
      _id: "..."
      title: "dorrisPage",
    },
    posts: [
      {
        isFetching: false,
        data: {
          _id: "..",
          body: ".."
        },
        comments: [..]
       }
    ]
  }
}

上述结构最初看起来不错,但我意识到我必须将action 传递给子状态。例如,如果我调度了一个名为

的动作
ADD_COMMENT

我会将操作传递给PagesReducerPostsReducerPostReducerCommentsReducer,最后CommentsReducer 将处理该操作。我想这是我意识到为什么在 Redux 中推荐 规范化状态

您能帮我解决以下问题吗?

  1. 在这种情况下,我对状态进行规范化的动机是否正确?
  2. 标准化示例状态的最佳方法是什么?

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    你应该避免嵌套

    来自 redux 文档的引用:

    在更复杂的应用中,您会希望不同的实体 互相参考。我们建议您保持您的状态为 尽可能标准化,没有任何嵌套。将每个实体保存在一个 以 ID 作为键存储的对象,并使用 ID 来引用它 其他实体或列表。将应用程序的状态视为数据库。这 方法在 normalizr 的文档中有详细描述。

    对于标准化状态,您可以使用normalizr

    pages:{
        items:{
            1:{id: 1,title: "dorrisPage", posts:[33,57]}
            2:{id: 2, title: "anotherPage",posts:[57]}
        },
        isFetching: false,
        itemIds:[1,2,..]
    },
    posts:{
        items:{
            33:{id: 33,title: "Post33", comments:[1,2]}
            57:{id: 57, title: "Post57", comments:[]}
        },
        isFetching: false,
        itemIds:[33,57,..]
    }
    comments:{
        items:{
            1:{id: 1, user: "user1", text:"fds"}
            2:{id: 2, user: "user2", text:"fds2"}
        },
        isFetching: false,
        itemIds:[1,2,..]
    }
    

    “itemIds”是物品订购所必需的

    那么 reducer 可能看起来像这样

    export const posts = (state = initialState, action) => {
        switch (action.type) {
    
            case type.FETCH_POSTS_REQUEST:
            case type.FETCH_POSTS_FAILURE:
                return {...state, isFetching: action.isFetching};
            case type.FETCH_POSTS_SUCCESS:
            return {...state,
                isFetching: action.isFetching,
                items: action.entities.posts, itemsIds: action.result
            };
    
            case type.DELETE_POST:
            return {...state,
                items: omit(state.items, action.id),
                itemsIds: state.itemsIds.filter(id=>id !== action.id)
            };
            case type.UPDATE_POST:
            return {...state, items: {...state.items,
                    [action.post.id]: {...state.items[action.post.id],...action.post}}};
    
            default:
            return state;
        }
    }
    

    更容易通过 id 查询帖子:

    const mapStateToProps = (state,ownProps) =({
        post:state.posts.items[ownProps.id]
    })
    

    为了计算来自 redux 存储的派生数据,您可以使用 Reselect 来创建记忆化、可组合的选择器函数

    video tutorial

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-04
      • 2016-01-30
      • 2021-08-13
      • 1970-01-01
      • 2017-11-07
      • 2020-08-06
      • 2020-12-29
      相关资源
      最近更新 更多