gpbaculio
gpbaculio

Reputation: 5968

My query is failing in relay and I don't know why?

I have this simple query which works fine in my Graphql but I cannot pass data using relay to components and I don't know why :(

{
  todolist { // todolist returns array of objects of todo
    id
    text
    done
  }
}

this is my code in an attempt to pass data in components using relay:

class TodoList extends React.Component {
  render() {
    return <ul>
      {this.props.todos.todolist.map((todo) => {
        <Todo todo={todo} />
      })}
    </ul>;
  }
}
export default Relay.createContainer(TodoList, {
  fragments: {
    todos: () => Relay.QL`
      fragment on Query {
        todolist {
          id
          text
          done
        } 
      }
    `,
  },
});

And lastly my schema

const Todo = new GraphQLObjectType({
    name: 'Todo',
    description: 'This contains list of todos which belong to its\' (Persons)users',
    fields: () => {
        return {
            id: {
                type: GraphQLInt,
                resolve: (todo) => {
                    return todo.id;
                }
            },
            text: {
                type: GraphQLString,
                resolve: (todo) => {
                    return todo.text;
                }
            },
            done: {
                type: GraphQLBoolean,
                resolve: (todo) => {
                    return todo.done;
                }
            },
        }
    }
});

const Query = new GraphQLObjectType({
    name: 'Query',
    description: 'This is the root query',
    fields: () => {
        return {
            todolist: {
                type: new GraphQLList(Todo),
                resolve: (root, args) => {
                    return Conn.models.todo.findAll({ where: args})
                }
            }
        }
    }
});

This code looks simple and I cannot see why this won't work and I have this error Uncaught TypeError: Cannot read property 'todolist' of undefined, but I configure todolist and I can query in my graphql, you can see the structure of the query is same, I don't know why this is not working?

Upvotes: 0

Views: 80

Answers (1)

Matthew Herbst
Matthew Herbst

Reputation: 31963

todolist should be a connection type on Query. Also, your ids should be Relay global IDs. You will not have access to your objects' raw native id fields in Relay.

import {
  connectionArgs,
  connectionDefinitions,
  globalIdField,
} from 'graphql-relay';

// I'm renaming Todo to TodoType
const TodoType = new GraphQLObjectType({
  ...,
  fields: {
    id: uidGlobalIdField('Todo'),
    ...
  },
});

const {
  connectionType: TodoConnection,
} = connectionDefinitions({ name: 'Todo', nodeType: TodoType });

// Also renaming Query to QueryType
const QueryType = new GraphQLObjectType({
  ...,
  fields: {
    id: globalIdField('Query', $queryId), // hard-code queryId if you only have one Query concept (Facebook thinks of this top level field as being a user, so the $queryId would be the user id in their world)
    todos: { // Better than todoList; generally if it's plural in Relay it's assumed to be a connection or list
      type: TodoConnection,
      args: connectionArgs,
    },
  },
});

// Now, to be able to query off of QueryType
const viewerDefaultField = {
  query: { // Normally this is called `viewer`, but `query` is ok (I think)
    query: QueryType,
    resolve: () => ({}),
    description: 'The entry point into the graph',
  }
};

export { viewerDefaultField };

The above is not fully complete (you'll likely also need to setup a node interface on one or more of your types, which will require node definitions), but it should answer your basic question and get you started.

It's a huge, huge pain to learn, but once you struggle through it it starts to make sense and you'll begin to love it over RESTful calls.

Upvotes: 1

Related Questions