react-apollo icon indicating copy to clipboard operation
react-apollo copied to clipboard

useLazyQuery: cannot read property 'subscribeToMore' of undefined when attempting to resubscribe

Open darrenfurr opened this issue 4 years ago • 5 comments

Intended outcome: Attempting to useLazyQuery & subscribeToMore with a changing variable to the query. NOTE - if I change this to useQuery it works as expected. I was trying to avoid the execution of the graphql query when the identifier is undefined (on initial component load)

Actual outcome: Cannot read property 'subscribeToMore' of undefined at QueryData._this.obsSubscribeToMore (QueryData.ts:476)

How to reproduce the issue: I have an input in Header component where you can enter the identifier which is written to apollo-cache. On initial PeopleContainer mount, the identifier is undefined. Then enter an identifier in the Header & hit Enter the LazyQuery & subscriptions execute correctly. Change the identifier & hit Enter again it throws the error above.

const PeopleContainer = () => {
  //get from ApolloCache
  const {
    data: {
      people: { identifier },
    },
  } = useQuery(GET_IDENTIFIER);

const [getPeople, { loading, data, error, subscribeToMore }] = useLazyQuery(GET_PEOPLE);

useEffect(() => {
    if (identifier) {
      getPeople({ variables: { identifier } });
    }
}, [identifier]);

useEffect(() => {
    if (identifier && subscribeToMore) {
      const updateUnsubcribe = subscribeToMore({
        document: UPDATE_PEOPLE
        variables: { identifier },
        updateQuery: (prev, { subscriptionData }) => handleUpdate(prev, subscriptionData),
      });

      const deleteUnsubscribe = subscribeToMore({
        document: DELETE_PEOPLE,
        variables: { identifier },
        updateQuery: (prev, { subscriptionData }) => handleDelete(prev, subscriptionData),
      });

      return () => {
        updateUnsubcribe();
        deleteUnsubscribe();
      };
    }
  }, [identifier, subscribeToMore]);

Version

System:
    OS: macOS Mojave 10.14.6
  Binaries:
    Node: 12.13.1 - /usr/local/bin/node
    Yarn: 1.22.0 - /usr/local/bin/yarn
    npm: 6.12.1 - /usr/local/bin/npm
  Browsers:
    Chrome: 80.0.3987.122
    Safari: 13.0.5
  npmPackages:
    @apollo/react-hooks: ^3.1.3 => 3.1.3 
    apollo-cache-inmemory: ^1.6.5 => 1.6.5 
    apollo-client: 2.6.8 => 2.6.8 
    apollo-link: ^1.2.13 => 1.2.13 
    apollo-link-ws: ^1.0.19 => 1.0.19

darrenfurr avatar Feb 26 '20 17:02 darrenfurr

I got the same error

System: OS: macOS Mojave 10.15.3 Binaries: Node: v13.0.1 - ~/.nvm/versions/node/v13.0.1/bin/node npm: 6.12.0 - ~/.nvm/versions/node/v13.0.1/bin/npm Browsers: Chrome: 80.0.3987.122 Safari: 13.0.5 npmPackages: "@apollo/react-hooks": "^3.1.3", "apollo-boost": "^0.1.28", "apollo-client": "^2.6.4", "apollo-link-context": "^1.0.9", "apollo-link-retry": "^2.2.10", "react-apollo": "^3.1.1",

jaredtmartin avatar Mar 06 '20 15:03 jaredtmartin

I got same issue. But found a workaround. I'm not sure if it is correct, but I got working it in this way (code is taken from first post):

const PeopleContainer = () => {
  //get from ApolloCache
  const {
    data: {
      people: { identifier },
    },
  } = useQuery(GET_IDENTIFIER);

const [getPeople, { called, refetch, loading, data, error, subscribeToMore }] = useLazyQuery(GET_PEOPLE);

useEffect(() => {
    if (identifier && !called) {
      getPeople({ variables: { identifier } });
    }
}, [getPeople, identifier, called]);

useEffect(() => {
    if (identifier && called) {
      refetch({ identifier });
    }
}, [refetch, identifier, called]);

useEffect(() => {
    if (identifier && subscribeToMore) {
      const updateUnsubcribe = subscribeToMore({
        document: UPDATE_PEOPLE
        variables: { identifier },
        updateQuery: (prev, { subscriptionData }) => handleUpdate(prev, subscriptionData),
      });

      const deleteUnsubscribe = subscribeToMore({
        document: DELETE_PEOPLE,
        variables: { identifier },
        updateQuery: (prev, { subscriptionData }) => handleDelete(prev, subscriptionData),
      });

      return () => {
        updateUnsubcribe();
        deleteUnsubscribe();
      };
    }
  }, [identifier, subscribeToMore]);

ghost avatar Mar 13 '20 09:03 ghost

I've encountered the same problem. I miss some examples on how to correctly combine useLazyQuery and subscribeToMore with variables validation (undefined)...

TeoTN avatar May 16 '20 15:05 TeoTN

Confirmed @ViktorsOvcinnikovs workaround. Any idea if this will get fixed in ApolloClient 3.0?

darrenfurr avatar Jun 11 '20 23:06 darrenfurr

With @ViktorsOvcinnikovs workaround the query and a refetch both are called on the first render. Not ideal but so far the only way to make this work. I wonder if this is not supported and we should run useSubscription instead and update the cache with the results.

immortalx avatar Jun 14 '20 23:06 immortalx