React redux normalizr:如何处理嵌套实体?

时间:2016-01-29 18:32:09

标签: javascript reactjs redux normalizr

我们假设我有一个这样的结构,这是从API获取并使用" normalizr"在我的实体上:

entities: {
    users:{
        1: {
            name: 'John',
            posts: [ 1, 4 ]
        }
    },
    posts: {
        1: {
            name: 'First Post',
        },
        4: {
            name: 'Second Post',
        }
    }
}

现在我有一个按用户过滤帖子的方法,基本上可以这样做:

let filteredPosts = {};
entities.users.posts.forEach(key => {
    if(posts.hasOwnProperty(key))
        filteredPosts[key] = posts[key]
});

显示该用户帖子的页面,例如:

render() {
    return(
        <div>
            {Object.keys(filteredPosts).map(key => {
                return (
                    <div>{filteredPosts[key].name}</div>
                );
            })}
        </div>
    )
}

我的实体reducer非常简单:

import { merge } from 'lodash';
...
function entities(state = { users: {}, posts: {} }, action) {
    if (action.response && action.response.entities) {
        return merge({}, state, action.response.entities);
    }
    return state;
}

现在,如果我向API请求为该用户添加帖子,返回新创建的帖子记录,该记录将自动添加到我的实体上的帖子中。

我如何处理更新用户以反映该更改,以便用户现在有3个帖子,数组中有新的帖子ID?

我应该创建一个reducer并听取帖子创建操作,并更新那里的state.entities.users.posts吗?重新构建实体似乎不是一种选择。最好的方法是什么?

由于

更新:

这是我现在必须使用的解决方案,以保持数据的一致性。我修改了对帐户创建的帖子ID的回复。我知道这可以分解为多个reducer,但我仍然想知道是否有更好更直接的方法,我不必为每个嵌套实体执行此操作。

function entities(state = {}, action) { 
    ...

    if(action.type === 'POST_ADD_SUCCESS') {
        // Get the user id from the created post
        let userId = response.entities.posts[response.result].userId;
        // Add the user with all his posts to the response
        response.entities.users = {
            [userId]: {
                posts: [...state.users[userId].posts, response.result]
            }
        }
    }
    ...
    // Merge normally
    return merge({}, state, response.entities);
}

3 个答案:

答案 0 :(得分:1)

您更新后的代码段主要沿着正确的路径展开,但我不确定您为什么仍然引用&#34;响应&#34;在那里。您的动作创建者函数可能应该抓取用户ID和帖子ID,并且当AJAX调用成功时,创建一个看起来像{type : POST_ADD_SUCCESS, userId : userId : postId}的动作。换句话说,减速器不应该知道任何关于“响应”的信息。根本就是它应该添加帖子ID&#39; x&#39;到用户ID列表&#39; y&#39;。

答案 1 :(得分:0)

为什么不使用normalizr作为中间件而不是自己滚动?像https://github.com/wbinnssmith/redux-normalizr-middleware

这样的东西

答案 2 :(得分:0)

您是否考虑在API成功发布时使用格式化实体调度新操作?

const foo = (entities) => { 
  type: "POST_ADD_SUCCESS"
  response : { entities }
}

操作类型无关紧要,因为您的实体reducer无论如何都会拦截操作