1

I am currently developing an analytics dashboard in React/Redux that is similar to this:

Analytics dashboard

Users of the dashboard will be able to add and remove tiles to customise the dashboard to their own needs, and the configuration of the tiles is stored and retrieved in an API.

The storing of the data for the configuration of tiles seems to fit well with the global state model:

  1. On load, the dashboard component dispatches a 'loadTiles' action
  2. The action fetches the tiles data and passes it to the 'tiles' reducer
  3. From there it goes into the store/global state.
  4. In mapStateToProps, the data is accessed from state.app.tiles

However, a problem arises when populating the data for each tile. The number of tiles and nature of the data is dynamic, so reducers can't be set up ahead of time.

This could be solved by each component managing their own state (as in pure/traditional React using componentWillMount etc) but this will violate some of the architectural principals that have been laid out for the rest of the project (ideally everything is to be managed in global state).

The only way I can see of storing the data is global state would be to have an analytics with a dynamic array of the various data sets, which sounds messy to me.

Is local component state the best solution here? or can this be done in global state cleanly? Are there any example of Redux using queries that are dynamically specified?

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Paul T Davies
  • 2,527
  • 2
  • 22
  • 39
  • @philipp 's answer is correct. It's also important to note that component state in a Redux app is fine, per this FAQ entry: http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state . – markerikson Mar 08 '17 at 16:03

1 Answers1

2

One thing you can do is the usage of an ID for each Tile. So your state could look like that:

{
  tiles: {
    tile1: {},
    …
    tile100: {}
  }
}

Than, in the mapStateToProps() function you can use own props like so:

function mapStateToProps(state, ownProps) {
  //test if it exists
  if (state.tiles[ownProps.id]) { 
    return { tileData: state.tiles[ownProps.id]  }
  }
  else
  {
    return { tileData: <default state> }
  }
}

The important part is to hand over a unique ID for each tile, when those are created, one way could be that:

<Tile id={uuid()} other="stuff" />

whereby the uuid() method can be created as described here

I once had an similar issue, have a look here if you want to see a more complicated solution using an higher order component (its my own unaccepted answer). All in all, the above is the simplest solution IMHO.

Community
  • 1
  • 1
philipp
  • 15,947
  • 15
  • 61
  • 106
  • This is kind of what I was getting at when I mentioned having a dynamic array of all the data sets. I does feel like hacking Redux rather than working with it though. – Paul T Davies Mar 08 '17 at 09:27
  • But that's the way it is. You can also create those IDs on the server and use them in the Frontend, but it will be the same essentially. – philipp Mar 08 '17 at 09:28
  • 1
    Using a single reducer with data separated by id is the normal way to use redux with dynamic data. I would add that if the tiles are of different types (with different functionalities), you could use different reducers (1 per tile type) – OlliM Mar 08 '17 at 15:17