4

I am trying to compose a react component with the following queries, but the query getMe is always an object and then I get TypeError: this.props.getMe is not a function. If I change it to a mutation then it all works. If I use the query in the graphiql web interface it works too. I am running out of ideas. Anyone spot something obvious.

The problematic part

const getMe = gql`
    query
    {
        viewer
        {
            _id
            name
            email
            gender
            birthday
            picture
            role
            facebookId
            facebookEmail
            token
        }
    }
`

export default compose(
  graphql(login, {name : 'authorizeUser'}),
  graphql(logout, {name : 'deauthorizeUser'}),
  graphql(getMe, {name : 'getMe'}),
)(App);

Here is the whole file

Just in case it helps

import React from 'react';
import { Button } from 'reactstrap'
import FacebookLogin from 'react-facebook-login';
import { compose, graphql } from 'react-apollo';
import gql from 'graphql-tag';
import './App.css';


class App extends React.Component
{
    constructor(props)
    {
        super(props);
        this.state = { loggedin: !!window.localStorage.getItem('token') };
    }

    login(res)
    {
        this.props.authorizeUser({
            variables: { accessToken: res.accessToken }
        })
        .then((data) => {
            console.log('got token', data.data.authorizeUser.token);
            window.localStorage.setItem('token', data.data.authorizeUser.token)
            this.setState({ loggedin: true, user: data.data.authorizeUser })
            console.log(this.state)
        }).catch((error) => {
            console.log('there was an error sending the query', error);
            window.localStorage.removeItem('token')
            this.setState({ loggedin: true })
        });
    }

    logout()
    {
        const token = window.localStorage.getItem('token')

        if (!token) {
            window.localStorage.removeItem('token')
            this.setState({ loggedin: false })
            return
        }

        this.props.deauthorizeUser({
            variables:{ token }
        })
        .then((data) => {
            console.log('destroyed token', data);
            window.localStorage.removeItem('token')
            this.setState({ loggedin: false })
        });
    }

    me()
    {
        const token = window.localStorage.getItem('token')

        console.log(this.props)

        this.props.getMe({
            variables:{ token }
        })
        .then((data) => {
            this.setState({ loggedin: true, user: data.data.authorizeUser })
        })
    }

    componentDidMount()
    {
        if (this.state.loggedin)
        {
            this.me()
        }
    }

    render()
    {
        return (
            <div className="App">
                <br/>
                { !this.state.loggedin &&
                    <FacebookLogin
                        appId="298798940239793"
                        autoLoad={false}
                        fields="name,email,picture"
                        callback={ this.login.bind(this) } />
                }
                { this.state.loggedin &&

                        <Button color="primary" onClick={ this.logout.bind(this) }>Logout</Button>
                }
                { this.state.loggedin && this.state.user &&
                    <div>
                        <img src={`http://graph.facebook.com/${this.state.user.facebookId}/picture?type=large`} alt="profile pic"/>
                        <div>{this.state.user.name}</div>
                        <div>{this.state.user.email}</div>
                        <div>{this.state.user.gender}</div>
                        <div>{this.state.user.birthday}</div>
                        <div>{this.state.user.role}</div>

                    </div>
                }
            </div>
        )
    }
}

const login = gql`
    mutation authorizeUser($accessToken: String!)
    {
        authorizeUser(accessToken: $accessToken)
        {
            _id
            name
            email
            gender
            birthday
            picture
            role
            facebookId
            facebookEmail
            token
        }
    }
`

const logout = gql`
    mutation deauthorizeUser($token: String!)
    {
        deauthorizeUser(token: $token)
        {
            success
        }
    }
`

const getMe = gql`
    query
    {
        viewer
        {
            _id
            name
            email
            gender
            birthday
            picture
            role
            facebookId
            facebookEmail
            token
        }
    }
`

export default compose(
  graphql(login, {name : 'authorizeUser'}),
  graphql(logout, {name : 'deauthorizeUser'}),
  graphql(getMe, {name : 'getMe'}),
)(App);

You can ignore the poor quality of this code, I am just playing around

3
  • Did you ever find a solution for this? I'm facing exactly the same problem! Commented Mar 29, 2018 at 9:49
  • yes I did actually let me look Commented Mar 29, 2018 at 10:54
  • @AndrewIsherwood Please check my answer and let me know if it worked Commented Mar 29, 2018 at 11:03

3 Answers 3

3

Finally found solution here

The points is

import { withApollo } from 'react-apollo'

class LoginForm extends Component {
// query by client.query
const queryUserResult = await this.props.client.query({
    query: QUERY_USER,
    variables: { name: value });
}

const MUTATION = gql`
mutation {
// some mutation logic
}
`

const QUERY = gql`
query {
// some query logic
}
`

export default compose(
    withApollo,
    graphql(MUTATION , { name: 'mutation' })
)(LoginForm))
Sign up to request clarification or add additional context in comments.

Comments

1

I see your main problem is with the syntax of the query. Below I give some examples of different queries using the gql from graphql-tag which you have used. Using these bits and pieces could hopefully help

Example 1:

const SIGNUP_MUTATION = gql`
mutation SignupMutation($email: String!, $password: String!, $name: String!) {
    signup(email: $email, password: $password, name: $name) {
        token
    }
}`

signup is the name of the resolver function in the backend

Example 2:

const FEED_QUERY = gql`
  query FeedQuery($first: Int, $skip: Int, $orderBy: LinkOrderByInput) {
    feed(first: $first, skip: $skip, orderBy: $orderBy) {
      links {
       id
       createdAt
       url
       description
       postedBy {
       id
       name
      }
      votes {
       id
       user {
        id
      }
    }
  }
  count
  }
 }`

Similarly here feed is the name of the resolver function int the backend.

Also you could try @compose(graphql(queryname , {name: 'logindata'}), graphql(...,{...}),...) at the top of your App class. This is how I have used recently.

Comments

0

I couldn't quite remember what I had done, but since I was asked about my solution I thought I would post the change I made.

// call it like this
this.viewer()

...

const me = gql`
    query user
    {
        viewer
        {
            _id
            name
            email
            gender
            birthday
            picture
            role
            facebookId
            facebookEmail
            token
        }
    }
`

export default compose(
  graphql(login, {name : 'authorizeUser'}),
  graphql(logout, {name : 'deauthorizeUser'}),
  graphql(me),
)(App);

1 Comment

Thanks for your suggestion :) I tried it and sadly it doesn't work for me, I just get: Uncaught TypeError: _this.getCall is not a function (where getCall is the name of my query).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.