8

Solved!

I'm trying to combine two dependent GraphQL queries.

The first one should get an ID and the second one should take that ID. I read that compose behaves like flowRight(), but no matter in what order I put the queries, if queryId is below queryDetails, queryDetail's is always skipped (as expected). No matter how I put my code together the variable is undefined.

import { graphql, compose } from 'react-apollo'
import gql from 'graphql-tag'

class Home extends Component {
  constructor(props) {
    super(props)
    console.log("Where's my data?")
    console.log(props)
  }

  render() {
    return(
      <div />
    )
  }
}

export const queryIdConst = gql`
  query IdQuery {
    account(name:"SuperAccount") 
    {
      lists {
        edges {
          id
        }
      }
    } 
  }
`

export const queryDataConst = gql`
  query DataQuery($id: ID!) {
    account(name:"SuperAccount") 
    {
      list(id: $id) {
        displayTitle
      }
    } 
  }
`

export default compose(
  graphql(queryIdConst, {
    name: 'listId',
  }),
  graphql(queryDataConst, { 
    name: 'data',
    skip: ({ listId }) => !listId.data,
    options: ({ listId }) => ({
      variables: {
        id: list.data.account.lists.edges[0].id
      }
    })
  })
)(Home)

I have already tried to change the compose functions order, but anyway this is not working, as I expected it to work.

Thanks for any help!

Edit: Switched the two graphql() in compose() to be inline with AbsoluteSith's comment link

Solution

With hints and help from Daniel Rearden and AbsoluteSith I implemented the following solution:

Changed the compose():

export default compose(
  graphql(queryIdConst, {
    name: 'listId',
  }),
  graphql(queryDataConst, { 
    name: 'dataHome', // changed to 'dataHome' to avoid confusion
    skip: ({ listId }) => !listId.account,
    options: ({ listId }) => ({
      variables: {
        id: listId.account.lists.edges[0].id
      }
    })
  })
)(Home)

And my render():

return(
  <div>
    { dataHome && !dataHome.loading && 
      <div>{dataHome.account.list.displayTitle}</div> 
    }
  </div>
)
psgmnd
  • 83
  • 1
  • 7
  • Have you tried [this](https://stackoverflow.com/questions/48880071/use-result-for-first-query-in-second-query-with-apollo-client) solution – AbsoluteSith Dec 06 '18 at 10:12
  • Thanks for your reply! Yes, that's where I came from. But my variables in the second Query are always undefined. I get the query object with all the functions, but data is undefined. In your link the variable is defined with 'firstQuery.data.someQuery.someValue', should I 'call' a query or is 'list.data.account.lists.edges[0].id' the right to access data? – psgmnd Dec 06 '18 at 10:21
  • Yeah try passing the right data ie; list.data.account.lists.edges[0].id. See the network calls made check if both the queries are executed and their order. But a better solution is to create a separate component for the second query – AbsoluteSith Dec 06 '18 at 10:40
  • Also [this](https://stackoverflow.com/questions/45511335/react-apollo-dont-run-query-on-component-load) might help too. Effectively you might not be accessing the data in the correct format/ hierarchy. – AbsoluteSith Dec 06 '18 at 11:39
  • 1
    Sorry saw your schema so you should be accessing the data as listId.account.lists.edges[0].id && check for listId value only – AbsoluteSith Dec 06 '18 at 11:45
  • Thanks for your help! Yes, I was a little bit confused by renaming and accessing and the lifecycle of the query and components. – psgmnd Dec 06 '18 at 12:09

1 Answers1

3

When using the graphql HOC, by default, the wrapped component receives a prop called data (or mutate if passing in a mutation). Given a query like

query IdQuery {
  account(name:"SuperAccount") {
    lists {
      edges {
        id
      }
    }
  } 
}

once the query loads, the query result is available under this.props.data.account. When you use the name configuration option, you're telling the HOC to use something other than data for the prop name. So if you set name to listId, then your query result will be available at

this.props.listId.account

That means the second HOC inside of compose should look more like this:

graphql(queryDataConst, { 
  skip: ({ listId }) => !listId.account, // <--
  options: ({ listId }) => ({
    variables: {
      id: listId.account.lists.edges[0].id // <--
    }
  })
})
Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • Perfect! Thanks for your help! I think I was confused with renaming and accessing afterwards. The second caveat was, that I thought the 2nd query should be listed as the 1st within my compose function, because the Doc states that it's called as flowRight(), but the 1st query must be above the 2nd, otherwise the 2nd doesn't know the 'listId'. confusion... Anyway, that's great and it is working now! – psgmnd Dec 06 '18 at 12:06