Normalizr + Redux - 更新单个实体的属性

3

我正在构建一个音乐播放器应用,使用REST API从各种端点(播放列表、某个用户发布的音轨等)获取音轨。

我使用redux和normalizr来管理我的状态。我创建了一个tracks实体,将track对象及其ID映射到其中。

简而言之,我的状态看起来有些像这样:

{
  playlists: {
    123: { id: 123, name: 'foo', tracks: [1, 2, 3] }
  },
  users: {
    me: { name: 'Niek', tracks: [2, 3] },
  },
  entities: {
    tracks: {
      1: { name: 'bar', user_favorited: false, ... },
      2: { name: 'foo', user_favorited: false, ... },
      3: { name: 'bar', user_favorited: true, ... }
    }
  }
}

这个功能目前对我来说运作得很好。但是现在我正在构建另一个API端点来切换曲目的收藏状态。
这个端点在响应中并不包含整个音轨资源,但我希望在API调用成功后更新单个音轨实体的user_favorited属性。
有什么最佳方法可以实现这一点吗?
作为一种解决方法,我现在在user_favorited端点调用成功后再从另一个端点重新获取整个音轨实体,但我希望找到一个优雅的解决方案,不需要这样做。

你最终解决了这个问题吗? - Matthew Brent
1个回答

1

我将提供两种解决方案:

  1. 重新获取数据。

  2. 更改实体。

其中一种方法是创建一个类似于以下的实体规约器:

const tracksReducer = (state, action) => {
    // Change the tracks
}

const entitiesReducer = (state, action) => {
    let _state = state;

    // Store all entities
    if (action.payload && action.payload.entities) {
        _state = merge({}, state, action.payload.entities);
    }

    return combineReducers({
        tracks: tracksReducer,
    })(_state, action);
};

export default { entities: entitiesReducer };

* 上面的代码使用了lodash的merge和redux的combineReducers


最近,我也在考虑完全不同的另一种结构,但尚未测试过,也没有找到任何其他人分享他们的经验。这个想法是完全删除第一级“实体”,并将它们存储在相应的键下。从理论上讲,当我们开始对实体进行更改时,这似乎是有道理的,并且将更容易地将所有类似的减速器、选择器等放在一个地方。
{
    tracks: {
        entities: {
            1: { name: 'bar', user_favorited: false, ... },
            2: { name: 'foo', user_favorited: false, ... },
            3: { name: 'bar', user_favorited: true, ... }
        },
        top3: [1, 2, 3],
        somethingAboutTracks: true
    },
    users: {
        entities: {},
        me: { name: 'Niek', tracks: [2, 3] }
    },
    playlists: {
        entities: {
            123: { id: 123, name: 'foo', tracks: [1, 2, 3] }
        }
    }
}

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