Search code examples
javascriptreactjsasynchronousgeolocationreact-apollo

Call graphql query with react-apollo with asynchronously fetched variables


I've got a react component which displays a map with points of interest near you.

My HOC uses react-apollo to query for those points of interests and give the data as props to the pure UI component.

I'm trying to get the position of the user from navigator.geolocation into the variables of my graphql query. But since the navigator API is asynchronous, I can't seem to make it work.

It looks about like this :

const getCurrentPosition = async (settings = {}) =>
  new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject, settings);
  }
);

const query = gql`
  query($coordinates: [[Float]]){
    whatever(filter: {coordinates: $coordinates}) {
      _id
      coordinates
    }
  }
`;

const withData = graphql(query, {
  options: async (props) => {
    const position = await getCurrentPosition();

    return {
      variables: {
        coordinates: [position.coords.latitude, position.coords.longitude],
      },
    };
  },
  props: ({ data: { loading, whatever, refetch, variables: { coordinates } } }) => ({
    loading,
    whatever,
    coordinates,
    refetch,
  }),
});


const List = ({ loading, whatever, coordinates, refetch }) => {
  if (loading) {
    return null;
  }
  return (/* map display*/);
};

List.propTypes = {
  loading: React.PropTypes.bool.isRequired,
  whatever: React.PropTypes.array,
  coordinates: React.PropTypes.array,
  refetch: React.PropTypes.func,
};

export default withData(Map);

coordinates is always null inside my component.

When I log things, it seems that the position is computed but the graphql query and the component rendering happen before it.

The query is not recalled and the component not re-rendered when we get the user location.

Is it possible ? Am I doing something wrong?


Solution

  • I would make the asynchronous call beforehand and inject it through props then use http://dev.apollodata.com/react/api.html#graphql-config.skip to skip the query if the position is not here yet.

    Maybe using recompose/withProps, etc. ?