【问题标题】:React redux normalizr: how to deal with nested entities?React redux normalizr:如何处理嵌套实体?
【发布时间】:2016-05-07 14:30:00
【问题描述】:

假设我有一个这样的结构,它是从 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。我知道这可以分解为多个减速器,但我仍然想知道是否有更好、更直接的方法,我不必为每个嵌套实体都这样做。

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);
}

【问题讨论】:

    标签: javascript reactjs redux normalizr


    【解决方案1】:

    您是否考虑在成功的帖子上向 API 发送带有格式化实体的新操作?

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

    动作类型无关紧要,因为您的实体减速器无论如何都会拦截动作

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您更新后的 sn-p 看起来大部分都在正确的路径上,尽管我不确定您为什么仍然在其中引用“响应”。您的操作创建函数应该获取用户 ID 和帖子 ID,当 AJAX 调用成功时,创建一个类似于 {type : POST_ADD_SUCCESS, userId : userId : postId} 的操作。换句话说,reducer 根本不应该知道任何关于“响应”的信息,只是应该将帖子 ID 'x' 添加到用户 ID 'y' 的列表中。

        【讨论】:

        • 这就是我说它可以分解为多个 reducer 的意思,在这种情况下,我只会引用状态本身而不是响应。关于如何使这个自动化的任何建议?如果这样做,我将不得不编写一堆嵌套的减速器,并且由于我正在使用减速器工厂,就像在 redux 的真实示例中一样,感觉它违背了目的。我的另一个想法是摆脱用户的 post 数组,而是使用非嵌套的 postsByUserId 减速器。这似乎是大多数人所做的,我只是不知道该怎么做。
        猜你喜欢
        • 2017-12-16
        • 2019-03-05
        • 2016-11-03
        • 2016-07-16
        • 2017-05-27
        • 2017-03-19
        • 2017-09-18
        • 2016-11-03
        • 2018-10-10
        相关资源
        最近更新 更多