项目作者: Freddy03h

项目描述 :
Normalize and Merge your application's data store using Immutable.JS objects
高级语言: JavaScript
项目地址: git://github.com/Freddy03h/immutable-data-structure.git
创建时间: 2017-09-02T14:48:58Z
项目社区:https://github.com/Freddy03h/immutable-data-structure

开源协议:

下载


Immutable-Data-Structure

BETA VERSION

Give me some feedback to improve the API and the Doc


Immutable-Data-Structure is a project to help you normalize and merge your application’s data using Immutable.JS objects.

It is useful to help manage your Redux store, it is created for this purpose, but Redux isn’t a dependency of this project so you basically can use it elsewhere.

It only provides functions :

  • Writing functions to use inside your reducers (merge, update, delete, … )
  • Reading functions to use inside your mapStateToProps (selectors)

Structure of the store

Assuming your already know why it’s important to normalize your data and to be resource oriented. Here is an example of a manga’s series reducer store.

The Immutable Record look like :

  1. const SerieRecord = Immutable.Record({
  2. id: null,
  3. title: null,
  4. type_id: null,
  5. })

And we also declare an array of all foreign keys for the Record :

  1. const serieForeignKeys = ['type_id']

The point of this project is to produce and maintain a structure like this :

  1. Immutable.Map {
  2. data: Immutable.Map {
  3. d1a38f41: Object {
  4. "id": "d1a38f41",
  5. "title": "Naruto",
  6. "type_id": "106f524e",
  7. },
  8. f0db2df6: Object {
  9. "id": "f0db2df6",
  10. "title": "Naruto : Les Romans",
  11. "type_id": "bb3d92a9",
  12. },
  13. a02cf154: Object {
  14. "id": "a02cf154",
  15. "title": "One Piece",
  16. "type_id": "106f524e",
  17. },
  18. f59ab8de: Object {
  19. "id": "f59ab8de",
  20. "title": "Radiant",
  21. "type_id": "3c009f18",
  22. },
  23. 96138837: Object {
  24. "id": "96138837",
  25. "title": "Dreamland",
  26. "type_id": "3c009f18",
  27. },
  28. b9652346: Object {
  29. "id": "b9652346",
  30. "title": "Fullmetal Alchemist",
  31. "type_id": "106f524e",
  32. },
  33. 940629b6: Object {
  34. "id": "940629b6",
  35. "title": "Dragon Ball",
  36. "type_id": "106f524e",
  37. },
  38. },
  39. relations: Immutable.Map {
  40. type_id: Immutable.Map {
  41. 106f524e: Immutable.OrderedSet [
  42. "a02cf154",
  43. "d1a38f41",
  44. "940629b6",
  45. "b9652346",
  46. ],
  47. 3c009f18: Immutable.OrderedSet [
  48. "96138837",
  49. "f59ab8de",
  50. ],
  51. bb3d92a9: Immutable.OrderedSet [
  52. "f0db2df6",
  53. ],
  54. },
  55. },
  56. }

Data

data stores all the resources with a quick access by id

Relations

relations store all the foreign keys relations like a relational database. It provides a fast access to resources based on a foreign key to avoid doing a filter directly on the data object that can be really huge and slow.

Selectors

If you already know Immutable.JS you know how to access data :

  1. state.getIn(['series', 'data', 'd1a38f41'])

But, it’s not recommended ! We provide selectors to easily access data and can change the structure internally without breaking / migrating your code.

getDataById

To get a Record knowing it’s ID.

  1. import { getDataById } from `immutable-data-structure`
  2. // ....
  3. // inside mapStateToProps
  4. const seriesID = 'd1a38f41'
  5. const serie = getDataById(state, 'series', seriesID)

getDataByIds

To get a List (Immutable.List) of Records by giving a Set (Immutable.Set) of IDs.

  1. const narutoSeriesIDs = Immutable.Set(['d1a38f41', 'f0db2df6'])
  2. const narutoSeries = getDataByIds(state, 'series', narutoSeriesIDs)

getForeignIds

To get the OrderedSet (Immutable.OrderedSet) of IDs by giving a ForeignKeys ID.

  1. const manfraTypeID = '3c009f18'
  2. const manfraSeriesIDs = getForeignIds(state, 'series', 'type_id', manfraTypeID)

It’s the equivalent of the not recommended Immutable.JS way :

  1. state.getIn(['series', 'relations', 'type_id', '3c009f18'])

getDataByForeignId

In many cases, getForeignIds is enough to use in the mapStateToProps of a list component. It’s recommended to .map IDs in the list and then connect each row by using getDataById inside the mapStateToProps of the row, for performance reason.

But sometimes, you need to order / filter / … the list based on Records attributes. So we need to get all the data.

getDataByForeignId return a List (Immutable.List) of Records by giving a ForeignKeys ID.

  1. const manfraTypeID = '3c009f18'
  2. const manfraSeries = getDataByForeignId(state, 'series', 'type_id', manfraTypeID)

You can think of this function like an easy version of something like this :

  1. const manfraTypeID = '3c009f18'
  2. const manfraSeriesIDs = getForeignIds(state, 'series', 'type_id', manfraTypeID)
  3. const manfraSeries = manfraSeriesIDs.map((serieID) => getDataById(state, 'series', serieID))

Manage (CRUD actions)

Functions to use in yours reducers.

updateRecord

Function to Create or Update one entity in the store. It automatically update data and relations to keep a consistent state.

For example inside a reducer :

  1. case FETCH_SERIE_SUCCESS: {
  2. const apiResponse = Immutable.fromJS(action.jsonResponse)
  3. const newStore = updateRecord(store, SerieRecord, apiResponse, serieForeignKeys)
  4. return newStore
  5. }

deleteRecord

Function to Delete one entity in the store.

  1. case DELETE_SERIE_SUCCESS: {
  2. const newStore = deleteRecord(store, action.seriesIDToDelete, serieForeignKeys)
  3. return newStore
  4. }