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, ... }
    }
  }
}

到目前为止,这对我来说非常有用。但现在我正在构建favorite通过调用另一个 API 端点来切换轨道状态的功能。

此端点不包括track响应中的整个资源,但我确实想在 API 调用成功后更新user_favorited单个实体的属性。track

实现这一目标的最佳方法是什么?

作为一种解决方法,我现在track在端点调用成功后再次从另一个端点获取整个实体user_favorited,但我希望找到一个不需要这样做的优雅解决方案。

4

1 回答 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 };

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


最近我也一直在考虑另一种结构,但还没有测试过,也没有发现其他人分享他们的经验。这个想法是完全删除第一级“实体”并将它们存储在相应的键下。从理论上讲,当我们开始对实体进行更改时似乎是有意义的,并且将所有类似的缩减器、选择器等放在一个地方会更容易。

{
    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] }
        }
    }
}
于 2019-04-24T09:06:35.450 回答