76

In the Apollo React docs http://dev.apollodata.com/react/queries.html#basics there are examples of fetching automatically when the component is shown, but I'd like to run a query when a button is clicked. I see an example to "re"fetch a query when a button is clicked, but I don't want it to query initially. I see there is a way to call mutations, but how do you call queries?

atkayla
  • 8,143
  • 17
  • 72
  • 132

2 Answers2

75

You can do it by passing a reference to Apollo Client using the withApollo higher-order-component, as documented here: https://www.apollographql.com/docs/react/api/react-apollo.html#withApollo

Then, you can call client.query on the passed in object, like so:

class MyComponent extends React.Component {
  runQuery() {
    this.props.client.query({
      query: gql`...`,
      variables: { ... },
    });
  }

  render() { ... }
}

withApollo(MyComponent);

Out of curiosity, what's the goal of running a query on a click event? Perhaps there is a better way to accomplish the underlying goal.

Sam Denty
  • 3,693
  • 3
  • 30
  • 43
stubailo
  • 6,077
  • 1
  • 26
  • 32
  • 4
    i wanted to use this for a search bar – atkayla Nov 22 '16 at 18:27
  • Im finding if I use this on a component which has the gql HOC on a parent, it triggers the parents componentWillReceiveProps. No idea why. Is there a better way? perhaps redux. – Craig Taub Dec 03 '16 at 20:42
  • 1
    This does not update the props? Why? How can I update props after the result comes in successfully? – Dee S Dec 06 '16 at 13:12
  • you can define an updateQuery function or updateQueries object in order to update the existing props – tahayk Dec 21 '16 at 16:07
  • Why can be that shows this error: `Error: Network error: Could not find query inside query map.`? – saeta Jan 28 '17 at 23:32
  • Are you using some persisted queries library? – stubailo Jan 30 '17 at 16:54
  • @stubailo Yes, I have disabled persisted queries and I can use it. Thanks. – saeta Feb 10 '17 at 13:49
  • @tahayk seems like updateQuery is not in client.query api, how we can archive that ? – smilingky Mar 25 '17 at 10:39
  • Sounds like this should be a new question - I'm not quite sure what you're trying to do. You might be able to use `client.writeQuery` though: http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.writeQuery – stubailo Mar 25 '17 at 19:10
  • Shouldn't you just fire the submit event and pass the input as props to another component which utilizes them in a query? – henk Oct 22 '17 at 21:55
  • is there a way to get `fetchMore()` from `this.props.client.query` like what `graphql()` has under `props.data.fetchMore()`? – spondbob Oct 26 '17 at 05:00
  • any ideas on this one? https://stackoverflow.com/questions/49238490/pass-variable-from-input-to-grapql-search-call – peter flanagan Mar 13 '18 at 15:48
  • 3
    In apollo 2.1 you can user component https://www.apollographql.com/docs/react/api/react-apollo.html#apollo-consumer... Also this ---> https://www.apollographql.com/docs/react/essentials/queries.html#manual-query – JohnSnow Apr 14 '18 at 16:37
27

As of version 3.0, you can do this in two ways now.

client.query

The first way is to call ApolloClient's query method. This returns a Promise that will resolve to the query's result. You can get a reference to the client by using the withApollo HOC:

class MyComponent extends React.Component {
  handleClick() {
    const { data } = await this.props.client.query({
      query: gql`...`,
      variables: { ... },
    })
    ...
  }
  ...
}

withApollo(MyComponent)

Alternatively, you can also use ApolloConsumer to get the client:

const MyComponent = () => (
  <ApolloConsumer>
    {client => {
      ...
    }
  </ApolloConsumer>
)

or the useApolloClient hook:

const MyComponent = () => {
  const client = useApolloClient()
  ...
}

useLazyQuery

The second way is to use the useLazyQuery hook:

const MyComponent = () => {
  const [runQuery, { called, loading, data }] = useLazyQuery(gql`...`)
  const handleClick = () => runQuery({ variables: { ... } })
  ...
}
Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • Hooks are headache when you need handle subscriptions. Potential of making mistakes and open too many subscription channels on the server is too high! ```useMemo``` will help but ```subscribeToMore``` is so dangerous :))) – Vahid Alimohamadi Nov 15 '19 at 16:03
  • useLazyQuery is just what we need for immediate load. Thanks. – azwar_akbar Nov 18 '20 at 13:04
  • I have to use `useApolloClient ` because I have a list of posts and each row of the list has an edit button. I want to get post data by its id and show data in a modal when I click on edit button. I tested `useLazyQuery` it doesn't get a post data again. I mean For the second and third time, I can not do this without refresh the page. – Ali Hesari Mar 18 '21 at 19:00
  • @FullOfStack you should add argument `fetchPolicy: 'network-only'` in your `useLazyQuery` – Siamko May 21 '21 at 05:51