5

I am following schema same as mentioned here

I want to fetch all users so I updated my schema like this

var Root = new GraphQLObjectType({
  name: 'Root',
  fields: () => ({
    user: {
      type: userType,
      resolve: (rootValue, _) => {
        return getUser(rootValue)
      }
    },
    post: {
      type: postType,
      args: {
         ...connectionArgs,
          postID: {type: GraphQLString}
        },
      resolve: (rootValue, args) => {
       return getPost(args.postID).then(function(data){
        return data[0];
       }).then(null,function(err){
        return err;
       });
      }
    },

    users:{
      type: new GraphQLList(userType),
      resolve: (root) =>getUsers(),
    },
  })
});

And in database.js

export function getUsers(params) {
  console.log("getUsers",params)
  return new Promise((resolve, reject) => {
      User.find({}).exec({}, function(err, users) {
        if (err) {
          resolve({})
        } else {
          resolve(users)
        }
      });
  })
}

I am getting results in /graphql as

{
  users {
    id,
    fullName
  } 
}

and results as

{
  "data": {
    "users": [
      {
        "id": "VXNlcjo1Nzk4NWQxNmIwYWYxYWY2MTc3MGJlNTA=",
        "fullName": "Akshay"
      },
      {
        "id": "VXNlcjo1Nzk4YTRkNTBjMWJlZTg1MzFmN2IzMzI=",
        "fullName": "jitendra"
      },
      {
        "id": "VXNlcjo1NzliNjcyMmRlNjRlZTI2MTFkMWEyMTk=",
        "fullName": "akshay1"
      },
      {
        "id": "VXNlcjo1NzliNjgwMDc4YTYwMTZjMTM0ZmMxZWM=",
        "fullName": "Akshay2"
      },
      {
        "id": "VXNlcjo1NzlmMTNkYjMzNTNkODQ0MmJjOWQzZDU=",
        "fullName": "test"
      }
    ]
  }
}

but If I try to fetch this in view as

export default Relay.createContainer(UserList, {
  fragments: {
    userslist: () => Relay.QL`
      fragment on User @relay(plural: true) {
            fullName,
            local{
              email
            },
            images{
              full
            },
            currentPostCount,
            isPremium,
      }
    `,
  },
});

I am getting error Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.

Please tell me what I am missing . I tried a lot with and without @relay(plural: true). Also tried to update schema with arguments as

    users:{
      type: new GraphQLList(userType),
      args: {
        names: {
          type: GraphQLString,
        },
        ...connectionArgs,
      },
      resolve: (root, {names}) =>connectionFromArray(getUsers(names)),
    },

but I got error Cannot read property 'after' of undefined in implementing react-relay Thanks in Advance.

8
  • Where do you define userslist? Commented Aug 4, 2016 at 17:04
  • I defined user list in routes.js Commented Aug 4, 2016 at 17:12
  • Relay.ql'{ users} Commented Aug 4, 2016 at 17:13
  • 1
    As the error suggested, did you try out non minified dev environment and get a detailed error message? Commented Aug 4, 2016 at 18:55
  • I got message Invariant Violation: RelayOSSNodeInterface: Expected payload for root field users to be a single non-array result, instead received an array with 5 results Commented Aug 5, 2016 at 6:13

1 Answer 1

8

Relay currently only supports three types of root fields (see facebook/relay#112):

  • Root field without arguments, returning a single node:
    • e.g. { user { id } } returning {"id": "123"}
  • Root field with one argument, returning a single node:
    • e.g. { post(id: "456") { id } } returning {"id": "456"}
  • Root field with one array argument returning an array of nodes with the same size as the argument array (also known as "a plural identifying root field"):
    • e.g. { users(ids: ["123", "321"]) { id } } returning [{"id": "123"}, {"id": "321"}]

A workaround is to create a root field (often called viewer) returning a node that has those fields. When nested inside the Viewer (or any other node), fields are allowed to have any return type, including a list or connection. When you've wrapped the fields in this object in your GraphQL server, you can query them like this:

{
  viewer {
    users {
      id,
      fullName,
    }
  }
}

The Viewer type is a node type, and since there will just be one instance of it, its id should be a constant. You can use the globalIdField helper to define the id field, and add any other fields you want to query with Relay:

const viewerType = new GraphQLObjectType({
  name: 'Viewer',
  interfaces: [nodeInterface],
  fields: {
    id: globalIdField('Viewer', () => 'VIEWER_ID'),
    users:{
      type: new GraphQLList(userType),
      resolve: (viewer) => getUsers(),
    },
  },
});

On the client you'll need to change the root query in your route to { viewer } and define the fragment on Viewer:

export default Relay.createContainer(UserList, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        users {
          fullName,
          local {
            email,
          },
          images {
            full,
          },
          currentPostCount,
          isPremium,
        }
      }
    `,
  },
});
Sign up to request clarification or add additional context in comments.

3 Comments

How should viewer looks like in my schema ?
@akshay I've now added an example Viewer type definition to my answer.
Thanks it woks like charm..:-)

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.