2
votes

I have a very simple app, with a list view and a detail view. The list view is wrapped with a graphql query that maps to a data prop containing an array of items. Selecting one item instantiates a detail view, where the id of the item is used to compose another graphql query for that one item.

const ListView = graphql(ALL_ITEMS, ...)(ListViewComponent);

<ListView data={ [....] }>
  <Detail>
      <Next /> <Prev /> {/* <-- need info from ListView.data */}          
  </Detail>
  { this.props.data.map(....) }
</ListView>

The trouble I'm having is adding previous/next navigation to that detail view. The detail component is unaware of what is in that data prop containing all the items in the ListView component. In a typical redux application, I would store the items as global application state, and injecting them into a component would be trivial, but Apollo doesn't seem to work that way. Its state tree is not very consumable (e.g. using connect()).

I see a few possible solutions for this, and none of them seem great:

  • Wrap the prev/next navigation component with a graphql query that looks for currentOffset + 1 and currentOffset -1. This is definitely the most "apollo" solution, but the problem there is that currentOffset is unknown to that component because it doesn't have the data prop. Further, I would have to ensure that any other variables (e.g. filters, sort) on the list view query got passed through, and those are in the obscure apollo state tree, as well.
  • Listen to the APOLLO_QUERY_RESULT action in my reducer and maintain a second copy of the query results with all the information my other components need.
  • Use context to share the data prop to children.
  • Explicitly pass the data prop to children.

Seems like a common scenario. What's the right approach?

1

1 Answers

3
votes

Passing data down as a prop would probably be the easiest solution.

One other option you may want to consider is simply wrapping whatever component you want to have access to the same query data with another graphql HOC. If you utilize the same query you use for ListView's HOC (ALL_ITEMS), you can use the data prop in your child just like you do in ListView. The neat thing about this approach is -- as long as you use the default fetchPolicy -- your child component will not trigger a second query against your server; it will simply utilize what's already in the cache.