1

Redux recommends your state be flat per here: https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

So say my state was like this:

{
    selectedPlaylistIndex: 0,
    pageDict: {},
    playlistDict: {},
    playlistList: []  // holds IDs from playlistDict
}

a sample Playlist Object would look like:

{
    id: someId,
    active: false,
    pageList: [], // holds IDs from pageDict
}

If I want to state create a Container for displaying the "pageList" of a Playlist object, I pass in the Playlists' "pageList" property as a list of the full Page objects (as opposed to the IDs). I feel like it's an expensive operation as anytime pageDict, playlistDict, playlistList, or selectedPlaylistIndex get updated, it will be rendered and the function will run.

Is there a more elegant / better way of doing this? I feel like I'm missing something.

// Expensive Operation; Want to Find Better Solution?
    getSelectedPlaylistPageObjArr() {
        const { selectedPlaylistIndex, pageDict, playlistDict, playlistList } = this.props;
        return playlistDict[ playlistList[ selectedPlaylistIndex ]].pageList.map( id => pageDict[id] ) : [];
      }

  render() {
    return (
      <Playlist
        pageObjArr={this.getSelectedPlaylistPageObjArr()}
      />
    );
  }


const mapStateToProps = ( state ) => {
  return {
    pageDict: state.entities.pageDict,
    playlistDict: state.entities.playlistDict,
    playlistList: state.entities.playlistList,
    selectedPlaylistIndex: state.application.selectedPlaylistIndex,
  };
};
user1189352
  • 3,628
  • 12
  • 50
  • 90

1 Answers1

1

Generalising, you're asking how to handle relational data.

Last time I had to deal with relational data I integrated redux-orm library. It's a small and immutable ORM to manage relational data in your Redux store.

So let's say your business logic is as follows 1 Playlist has many Pages, then in order to get the Pages of the selected Playlist (by playlist's id), it would be computed with redux-orm as follow:

const getSelectedPlaylistId = state => state.application.selectedPlaylistIndex

const getPlaylistPages = createSelector(
    orm,
    getSelectedPlaylistId,
    ({ Playlist }, playlistId) => {
        return Playlist.withId(playlistId).Pages.all().toRefArray();
    }
);

Once you invoked getPlaylistPages the result will be cached and recalculated only when one of the accessed models are changed.

Also if you don't want to use redux-orm (let's assume your app doesn't have a lot of models or any other reason), then you can just use reselect library, that will cache your performance cost computations.

As I already mention I had such an experience, and my thoughts and conclusions are summarized in the following SO question: How to deal with relational data in Redux?

Jordan Enev
  • 16,904
  • 3
  • 42
  • 67
  • thank you i really appreciate you responding to this. i'm going to start doing my research into everything you linked right now. thank you – user1189352 Jul 23 '18 at 16:36