简体   繁体   中英

User Apollo GraphQL with promise

I am building the React native app with GraphQL. I have to make a data call once i received and event from native layer when the app comes in foreground.

const eventEmitter = new NativeEventEmitter(NativeModules.EventEmitter)
    if (eventEmitter.listeners(Constants.callBacks.NativeSideEventReceived).length === 0) {
      eventEmitter.addListener(Constants.callBacks.NativeSideEventReceived, (linearIngressData) => {
        
const {data, error} = useQuery(CONTENT, {
  variables: {
    deviceLocale,
    contentId,
    contentType: Json
  },
  skip: shouldSkip
})


      })
    }

Problem is, I can not use useQuery inside the event handler as to use the useQuery i have to be inside the react component.

Once data is available then i have to dispatch some event.

const dispatch = useContext(DispatchContext)
if (data) {
    dispatch({
      type: '_CHANGE',
      content: data.content
    })
  }

How can i use promise object with GQL to make sure data is available. If i receive the NativeSideEventReceived before data is available then i have to wait until i have response available to dispatch state event.

I can not use onComplete function of useQuery, since to use useQuery i have move this to a functional component but Once i have event received the event then only i have to dispatch the event. Using onComplete will not have guaranty that onComplete will be called after event NativeSideEventReceived received.

Thanks

As a Vue user I've created this little composable function in order to have a promisified version of the apollo APIs.

import { ApolloQueryResult, OperationVariables } from '@apollo/client';
import { useQuery } from '@vue/apollo-composable';
import { DocumentParameter, VariablesParameter } from '@vue/apollo-composable/dist/useQuery';
import { ref } from 'vue';


// promisification of the apollo query
export function useApolloQuery<TResult = any, TVariables extends OperationVariables = OperationVariables>(document: DocumentParameter<TResult, TVariables>, variables: () => VariablesParameter<TVariables>) {
  const enableLoginQuery = ref(false);
  const { onResult, loading: queryLoading, onError } = useQuery(
    document, 
    variables,
    () => ({
      enabled: enableLoginQuery.value,
      notifyOnNetworkStatusChange: false
    }));

  const apolloQuery = () => new Promise<ApolloQueryResult<TResult>>((resolve, reject) => {
    console.log('calling query apollo');
    enableLoginQuery.value = true;
    onResult(res => {
      if (!res.loading) {
        enableLoginQuery.value = false;
        
        if (!res.data) {
          reject('no data');
        }
        resolve(res);
      }
    });
    onError(err => {
      enableLoginQuery.value = false;
      console.error(err)
      reject(err);
    });
  });

  return {
    apolloQuery,
    queryLoading
  };
}

On a sample query you would use it like this:

import {useApolloQuery} from '... wherever that is';

const { apolloQuery } = useApolloQuery(UserQueryDoc, () => ({
  username: form.value.username,
  otherVars: 'other sample var'
}));
const res = await apolloQuery();

All fully typed. I use graphql-tools to generate the types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM