Unable to fetch list in react relay
Asked Answered
H

1

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.

Howe answered 4/8, 2016 at 15:3 Comment(8)
Where do you define userslist?Lyse
I defined user list in routes.jsHowe
Relay.ql'{ users}Howe
As the error suggested, did you try out non minified dev environment and get a detailed error message?Lyse
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 resultsHowe
Which version of Relay are you using? List-type root field in query is now supported.Lyse
here are versions list of all relays packages , "react-relay": "0.8.1", "graphql-relay": "0.4.1", "isomorphic-relay-router": "0.8.0-beta.0", "isomorphic-relay": "0.7.0-beta.0", "relay-local-schema": "0.5.0", "babel-relay-plugin": "0.8.1",Howe
It may be a good idea to look at star-wars example of relay. It also has a query where a root query field is a list.Lyse
I
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,
        }
      }
    `,
  },
});
Including answered 7/8, 2016 at 10:51 Comment(3)
How should viewer looks like in my schema ?Howe
@Howe I've now added an example Viewer type definition to my answer.Including
Thanks it woks like charm..:-)Howe

© 2022 - 2024 — McMap. All rights reserved.