React Redux Normalizr:如何处理嵌套实体?

5
假设我有一个这样的结构,它是通过调用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>
    )
}

我的实体减速器非常简单:

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。我知道这可以分解成多个reducers,但我仍然想知道是否有更好和更直接的方法,而不必为每个嵌套实体都这样做。
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个回答

1
你更新的代码片段基本上走在正确的道路上,尽管我不确定为什么你还在引用 "response"。你的 action creator 函数应该抓取用户 ID 和帖子 ID,当 AJAX 调用成功时,创建一个看起来像 {type : POST_ADD_SUCCESS, userId : userId : postId} 的操作。换句话说,reducer 不应该知道任何关于 "response" 的信息,只需要将帖子 ID 'x' 添加到用户 ID 'y' 的列表中即可。

这就是我说的可以分解成多个reducer的意思,那么在这种情况下,我只需引用状态本身而不是响应。有什么自动化的建议吗?如果这样做,我将不得不编写一堆嵌套的reducers,而且由于我正在像redux中的真实示例一样使用reducer工厂,所以感觉它违背了初衷。我另一个想法是摆脱用户上的post数组,而是拥有一个非嵌套的postsByUserId reducer。这似乎是大多数人做的事情,只是我不确定如何去做。 - Thomas Monte

0
你有没有考虑在 API 成功提交后,使用格式化的实体分派新的操作?

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

无论操作类型如何,您的实体 reducer 都会拦截该操作。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接