Brandon Willis
Brandon Willis

Reputation: 145

React Native: Why Does GraphQL Query With Apollo Return Undefined?

I'm currently trying to take a GraphQL query and using Apollo, display the result on my React Native app.

Here is the relevant code in App.js:

import {LoginScreen} from './src/Screens'
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

const myLink = new HttpLink({
  uri: 'http://localhost:5000/graphql',
});

const client = new ApolloClient({
  link: myLink,
  cache: new InMemoryCache()
});

export default class App extends React.Component{
  render() {
    return(
      <ApolloProvider client={client}>
        <LoginScreen/>
      </ApolloProvider>
    )}
}'

And here is the relevant code in LoginScreen.js

function ShowUser({data: { loading, otsUserByUserId }}) {
    if (loading) {
      return <Text>Loading</Text>;
    } else {
        console.log("Ots user is " + otsUserByUserId)
        console.log("Data: " + data)
      return (
        <View>
            {otsUserByUserId.map(user =>
                <Text>The name of user is {user.firstName} {user.lastName}.</Text>
            )}
        </View>
      );
    }
  }

export default graphql(gql`
    query otsUser{
        otsUserByUserId(userId:1) {
            firstName
            lastName
        }
    }
`)(ShowUser)

My query works in GraphiQL as you can see: Graphiql Query

And just to show that I'm using the correct endpoint for my link: Start GraphQL Server

When running this, in my debugger, I see Chrome Developer Tools Response

This shows that data is undefined and it's a networking error. So I must be doing something wrong on my setup on the front end. In some way, I am not using Apollo correctly. It seems pretty obvious that the error is in my App.js in how I define client, but I haven't been able to get anything to work for a while now, and it's driving me nuts. I can't find any SO posts on this.

I've gone through the Apollo docs multiple times and have been trying to just get something to work for a few days now. Any help is much appreciated. Thank you for your time.

Upvotes: 2

Views: 2545

Answers (1)

Chris Geirman
Chris Geirman

Reputation: 9684

The problem is localhost only means something to your computer, but means nothing to your react native app since the server is not running on it. Try changing localhost to your computer's IP address. That should hook you up.

const myLink = new HttpLink({
  uri: 'http://{COMPUTER_IP_ADDRESS_HERE}:5000/graphql',
});

Update: 11/21

Below is to deal with your additional questions left in the comments.

  1. If you have a better idea, please do not hesitate to tell me and I will try it.
  2. Why can't I just do console.log(props.data)?

1. How I've done it

Here's a copy/paste of a working login page from one of my demo/toy apps. I know it works. It basically does the same thing you're attempting with a couple nice additions (e.g. managed form state, passing vars to the HOC, localstorage caching). You should be able to get what you need from it and adapt it to your use case easily.

// LoginScreen.js
import React from 'react';
import { gql, graphql } from 'react-apollo';
import { Button, Input } from 'rebass';

import { AUTH_TOKEN_KEY } from '../config';

class Login extends React.Component {
  state = {
    form: {
      email: '',
      password: ''
    },
    submitting: false
  };

  handleSubmit = evt => {
    evt.preventDefault();
    this.setState({
      submitting: true
    });

    const { email, password } = this.state.form;
    this.props
      .signinUser({ variables: { email, password } })
      .then(res => {
        window.localStorage.setItem(AUTH_TOKEN_KEY, res.data.signinUser.token);
        window.location = '/';
      })
      .catch(err => console.error(err));
  };

  handleChange = evt => {
    const { name, value } = evt.target;

    this.setState({
      form: {
        ...this.state.form,
        [name]: value
      }
    });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <h1>Login</h1>
        <Input
          type="text"
          name="email"
          label="Email"
          value={this.state.form.email}
          // baseRef={ref => ref.focus()}
          onChange={this.handleChange}
        />
        <Input
          type="password"
          name="password"
          label="Password"
          value={this.state.form.password}
          onChange={this.handleChange}
        />
        <Button>Login</Button>
      </form>
    );
  }
}

const signinUser = gql`
  mutation($email: String!, $password: String!) {
    signinUser(email: { email: $email, password: $password }) {
      token
    }
  }
`;

export default graphql(signinUser, { name: 'signinUser' })(Login);

2. console.log(props.data)

You should be able to log this. Not sure what you're seeing, but I'm assuming it's something like [Object] from your description. If that's true, try this console.log('props.data %j', props.data) which will convert props.data to json if possible. You can also try console.log({props}) to see the entire props tree. If neither works the way you want, then you probably have something else going on here.

If you have more questions, you should probably open new stack overflow questions. These are really meant to just be one-to-one kinds of things, one question, one answer.

Upvotes: 2

Related Questions