apollographql / react-apollo

:recycle: React integration for Apollo Client
https://www.apollographql.com/docs/react/
MIT License
6.85k stars 787 forks source link

Refetch does not work with variables #1929

Closed pbandjs closed 5 years ago

pbandjs commented 6 years ago

I am trying to implement a straightforward search on react-native. I was previously using react-apollo 1.x, and the following snippet worked fine ie when i change the search state in Wrapper, the List component reruns with the new value of search.

class Wrapper extends React.Component {
  state={
    search:""
  }

  render(){
    return (<View>
      <ListWithQuery search={search} />
    </View>)
  }
}

class List extends React.Component {

  render(){
    return (
      <View>
        //...some stuff here
      </View>
    )
  }
}

const ListWithQuery=graphql(SOME_QUERY, {
  name: "someQuery",
  options: props => {
    return {
      variables: {
        search: props.search || null
      }
    }
  }
})(List)

I just cannot figure out how to do the same with the new Query component. I have tried replacing ListWIthQuery with the new Query component like below. But the list does not refetch when search changes.

class Wrapper extends React.Component {
  state={
    search:""
  }

  render(){
    return (
      <Query query={SOME_QUERY} variables={{search:this.state.search}}>
        {({data,refetch})=>{
          return (
            <View>
              <List />
            </View>
          )
        }}
      </Query>
    )
  }
}

I also tried using the refetch function in the renderProps of query to manually trigger a refetch with new variables whenever the search state is changed(see below snippet). This refetches the query but i cannot seem to pass in the new search variable.

class Wrapper extends React.Component {
  state={
    search:""
  }

  render(){
    return (
      <Query query={SOME_QUERY}>
        {({data,refetch})=>{
          return (
            <View>
              <List />
              <TouchableOpacity
                onPress={()=>{
                  refetch({search:this.state.search})
                }}
                />
            </View>
          )
        }}
      </Query>
    )
  }
}

In my opinion, this is a real basic use case and it worked fine with the old pattern of wrapping components with graphql(), but I just cannot get it to work with the new Query Component. I cannot find anything in the docs which leads to a solution. Am i going about this the wrong way? Can someone please help with this.

wuzhuzhu commented 6 years ago

+1

chengcyber commented 6 years ago

I run into this issue now, but I think we might have misunderstanding on this function. In my case, I set variables(paginateBy = 1) in Query hoc, and refetch (set paginateBy = 2) inside the component. After my refetch triggered, the variables is not updated, such as: image

Actually the refetch works, because you can check the variables update in Network tab of Chrome dev tool, such as: image

expects this is helpful to some one run into this issue.

dendrochronology commented 6 years ago

I'm having the same issue as @kimochg; calling refetch({ page: 2 }) returns the same results on the data prop (e.g., {page: 1}), even though the network panel shows it hit the server and got new results.

Is there some missing step, or is this a bug?

Kisepro commented 6 years ago

Same for me, the only two ways it's working for me it's with

japrogramer commented 6 years ago

Same here, except im doing something like this


addNote({
        variables: { text: this.state.text, id: resource },
        refetchQueries: ['searchResourcesPaged', 'DetailResourceQuery'],
      })

where searchResourcesPaged takes a page int, I want to re use the one that was previously used. in my case it does not refetch

tejaswinichile commented 5 years ago

Any updates on this issue? I am trying to build pagination, I can see the refetch with updated variable {page: 2} hitting the server but not updating the props.data

mufasa71 commented 5 years ago

I think I know when its happens: If <Query variables={someInitialVars} /> is used as child and when parent component triggers re-render, <Query /> will be called with initial vars instead of refetch(newVars), probably because of async nature. So simply making child as pure fixing the issue.

Main advice will be to not use initial vars and refetch in same time in react, better to use default values in grapqhl query itself, or make initial vars controlled and don't use refetch.

I don't know which is proper fix will be in react-apollo, but we can put in documentation at least.

andersonl-selina commented 5 years ago

Same here, I am using other config options I hope it doesn't matter:

graphql(STAY_PRODUCTS_AVAILABILITY_QUERY, {
  name: 'availabilityQuery',
  alias: 'withAvailabilityQuery',
  skip: ({userOptions = {}}) => !userOptions.location,
  options: ({userOptions = {}}) => {
    const {location, checkIn, checkOut} = userOptions
    const variables = {
      locationId: location.id,
      ciDate: dateToQueryDateFormat(checkIn),
      coDate: dateToQueryDateFormat(checkOut)
    }
    return {variables}
  }
})
andersonl-selina commented 5 years ago

Same here, I am using other config options I hope it doesn't matter:

graphql(STAY_PRODUCTS_AVAILABILITY_QUERY, {
  name: 'availabilityQuery',
  alias: 'withAvailabilityQuery',
  skip: ({userOptions = {}}) => !userOptions.location,
  options: ({userOptions = {}}) => {
    const {location, checkIn, checkOut} = userOptions
    const variables = {
      locationId: location.id,
      ciDate: dateToQueryDateFormat(checkIn),
      coDate: dateToQueryDateFormat(checkOut)
    }
    return {variables}
  }
})

Fixed adding the flag to skip the cache in the specific fragments with field id that I don't wanna cache:

# Disable Apollo caching
__typename @skip(if: true)

Reference: https://kamranicus.com/posts/2018-03-06-graphql-apollo-object-caching

pl12133 commented 5 years ago

Looks a lot like https://github.com/apollographql/apollo-client/issues/2285

elliscwc commented 5 years ago

This was my solution before using apollo client and writing to cache:

const { client } = this.props;
const { cache } = client;
const { data } = await client.query({
    fetchPolicy: 'network-only',
    query: YourQuery,
    variables: {
        ...variables with new options
    },
});
await cache.writeQuery({
    query: YourQuery,
    data,
    variables: {
        ...variables from first query e.g <Query variables={from here}>
    },
});

No longer an issue to use refetch(new variables); after update client to

"apollo-client": "2.6.2",
"react-apollo": "2.5.6",
khaphannm commented 5 years ago

Anyone has a solution for this issue. I still get stuck with refetch function. It doest not return the updated data when passing new variables

tejaswinichile commented 5 years ago

@khaphannm I don't remember it correctly but my issue got resolved by changing fetchPolicy="no-cache"

Please check if it works in your case.

Or it should work with fetchPolicy: 'network-only' as @elliscwc mentioned.

hwillson commented 5 years ago

React Apollo has been refactored to use React Hooks behind the scenes for everything, which means a lot has changed since this issue was opened (and a lot of outstanding issues have been resolved). We'll close this issue off, but please let us know if you're still encountering this problem using React Apollo >= 3.1.0. Thanks!

ssteiger commented 4 years ago

This error is still present in "react-apollo": "3.1.3"

graphql(getLocations, {
  props: ({ data: { users, refetch, updateQuery, loading, error } }) => {
    // ERROR HUNT: The problem is that the previously used query variables
    //             are not removed when passing new variables
    //             this can be observed in the apollo console
    return {
      title: 'Locations',
      locations,
      refetch,
      updateQuery,
      loading,
      error
    }
}

and in component:

handleSubmit = () => {
    const {
      form: { getFieldsValue },
      updateQuery,
      refetch
    } = this.props

    let fields = getFieldsValue()
    fields = omit(fields, value => value == null || value === '')

    // this is not working, variables used in previous query are not updated/removed
    //refetch({ ...fields, dummy: Math.random() })
    refetch({ ...fields })
  }

Example:

Run query with let fields = { id: "5e36e69924aa9a0007624981", name_contains: "Bob" }

Apollo "watch query" console output:

Variables:

id="5e36e69924aa9a0007624981",
name_contains="Bob"

Then run query with let fields = { name_contains: "Marie" }

Apollo "watch query" console output:

Variables:

id="5e36e69924aa9a0007624981",
name_contains="Marie"
LeeroyJenks commented 4 years ago

This error is still present in "react-apollo": "3.1.3"

graphql(getLocations, {
  props: ({ data: { users, refetch, updateQuery, loading, error } }) => {
    // ERROR HUNT: The problem is that the previously used query variables
    //             are not removed when passing new variables
    //             this can be observed in the apollo console
    return {
      title: 'Locations',
      locations,
      refetch,
      updateQuery,
      loading,
      error
    }
}

and in component:

handleSubmit = () => {
    const {
      form: { getFieldsValue },
      updateQuery,
      refetch
    } = this.props

    let fields = getFieldsValue()
    fields = omit(fields, value => value == null || value === '')

    // this is not working, variables used in previous query are not updated/removed
    //refetch({ ...fields, dummy: Math.random() })
    refetch({ ...fields })
  }

Example:

Run query with let fields = { id: "5e36e69924aa9a0007624981", name_contains: "Bob" }

Apollo "watch query" console output:

Variables:

id="5e36e69924aa9a0007624981",
name_contains="Bob"

Then run query with let fields = { name_contains: "Marie" }

Apollo "watch query" console output:

Variables:

id="5e36e69924aa9a0007624981",
name_contains="Marie"

I'm also experiencing the same issue. Has there been any update on this?

khalednabawy commented 4 years ago

this error still apear with me