microman
microman

Reputation: 161

Rendered more hooks than during the previous render

How to use 2 graphql queries with react-apollo-hooks where the 2nd query depends on a parameter retrieved from the 1st query?

I try to use 2 queries which looks like this:

const [o, setO] = useState()

const { loading: loadingO, error: errorO, data: dataO } = useQuery(Q_GET_O, { onCompleted: d => setO(d.getO[0].id) });

if (loadingO) { return "error" }

const { loading: loadingOP, error: errorOP, data: dataOP } = useQuery(Q_GET_OP, { variables: { o } })

However, when I run my project, react-hooks gives me the following message:

"index.js:1437 Warning: React has detected a change in the order of Hooks called by Upgrade. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks"

I would like to know how I can use react-apollo-hooks in order to run a query that depends on another query. It works great if the graphql query variables are known in advance. However, I did not find a solution for variables that come from other query.

Upvotes: 3

Views: 7144

Answers (2)

rishikarri
rishikarri

Reputation: 4520

The problem here is that you are short circuit returning before all of your hooks have a chance to run.

React will complain if you exit a render function before all of the hooks have a chance to be called.

For example:

function BrokenFoo () {
  const query = useSomeQuery();
  if (query.loading) return <Loading />

  // This will cause some issues because 
  // it's possible that we return before our useState hook gets called

  const [bar, setBar] = useState();

  return <SomeComponent bar={bar} setBar={setBar} data={query.data} />
}

To fix:

function FixedFoo () {
  // This will be fine because 
  // all of the hooks have a chance to be called before a return
  const query = useSomeQuery();
  const [bar, setBar] = useState();

  if (query.loading) return <Loading />

  return <SomeComponent bar={bar} setBar={setBar} data={query.data} />
}

Upvotes: 8

thathat
thathat

Reputation: 595

You can add the skip option to the second query and lose the if condition:

const { loading: loadingOP, error: errorOP, data: dataOP } 
    = useQuery(Q_GET_OP, { variables: { o }, skip: !o  })

from the docs: If skip is true, the query will be skipped entirely

Upvotes: 3

Related Questions