Example (you might skip this)
Say there is an app which helps people to organise their music library. The library contains Albums
, each Album
contains separate Songs
, each Song
contains popular Quotes
which appear in that song. For Each of these objects there is more information, so the Album
object holds information about the artist, year etc. Users can edit all of that.
My problem
I am struggling to find the most effective strategy to convert this into Redux. I was thinking of nesting everything like albums: [ { title, songs: [etc. etc.]}, {}]
So there we have all the data in one object. However, if somebody clicks on an album, a song and a quote my reducers will somehow need to know what to display and what the user is currently engaging with.I can think of 2 approaches to this:
Approach 1
{
list: [] //contains all albums, songs, quotes as outlined above
currentAlbum: albumId
currentSong: songId
currentQuote: quoteId
}
Approach 2 Have different parts of state hold not only the ids, but the whole object:
listReducer: [] // holds the list, same as above
currentAlbumReducer: { id: albumid12312, title: "The Eminem Show", etc... }
currentSongReducer: { id: songid4545, song_title: "I believe", etc... }
currentQuoteReducer: { id: 12312, quote: "I'm Slim Shady", etc... }
On this approach I would always move things from the list into the appropriate 'current' reducers and if somebody changes anything here I would then at some later point update the lists.
However, it seems a bit redundant. At the same time, might this approach be faster than storing everything in one single object?
I would appreciate some advice here what is the best method and why, and whether there are maybe other ways of handling state that didn't occur to me.
This is where the concept of normalizing your state comes into play. As a summary, that generally means storing items using objects as lookup tables keyed by item IDs, and referencing items elsewhere using those IDs.
So, in your case, your state tree might look like:
{
albums : {
albumid1 : {title, songs : ["songid1", "songid2"] }
},
songs : {
songid1 : {title}
},
quotes : {
quoteid1 : {text}
},
currentSelections : {
album : "albumid1",
song : "songid1",
quote : "quoteid1"
}
}