2

How am I supposed to (re)query the object when id is different on every load? What am I missing?

const {nodeInterface, nodeField} = nodeDefinitions(
  (globalId) => {
    const {type, id} = fromGlobalId(globalId);

    // This id is different every time (if page is reloaded/refreshed)
    // How am I suppose to use this id for database query (e.g by id)?
    // How do I get "the right ID"? (ID actually used in database)
    console.log('id:', id);

    // This is correct: "User"
    console.log('type:', type);

    if (type === 'User') {
        // Function that is suppose to get the user but id is useless ..
        return getUserById(id);
    } 
    return null;
  },

  (obj) => {
    if (obj instanceof User) {
        return userType;
    } 
    return null;
  }
);

const userType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
      id: globalIdField('User'),      // Relay ID
      _id:   { type: GraphQLString }, // MongoDB ID
      email: { type: GraphQLString },
      name:  { type: GraphQLString }    
  }),
  interfaces: [nodeInterface]
});
Solo
  • 6,687
  • 7
  • 35
  • 67
  • Why would your `id` change on every reload? The `id` is set by the server, so it can (and should) be consistent across reloads. The `fromGlobalId` function just takes the `id` field off the object returned by your `getUserById` function and merges it with the `"User"` string – NevilleS Aug 08 '16 at 22:52
  • @NevilleS It's not same across reloads.. Any idea what could be the reason? – Solo Aug 08 '16 at 23:03
  • Where is it "changing"? You mean, in the React client code? If so, you're probably just arbitrarily inventing `id`s in the client when you should be using legit `id`s returned by your server – NevilleS Aug 08 '16 at 23:35
  • @NevilleS How does it generate global ID in the first place? How does database ID even get there (which I should be able to retrieve and use in database query)? All I give it is `id: globalIdField('User')` but `_id` is the real deal (object ID in database). – Solo Aug 08 '16 at 23:49

1 Answers1

2

Global ID is primarily used for refetching objects which are already in the Relay client store. I'll DRY and point to an excellent related SO post, which nicely explains how global ID is used in Relay.

If you use helper functions from libraries, for example, graphql-relay-js in JavaScript, dealing with global ID becomes pretty straight-forward:

  1. You decide that server-side object type X corresponds to GraphQL object type Y.
  2. Add a field id to X. This id is the local ID and it must be unique for any object of type X. If X corresonds to a MongoDB document type, then a simple approach is to assign the string representation of _id to this id field: instanceOfX.id = dbObject._id.toHexString().
  3. Add a field id to Y by using globalIdField helper function. This id is the global ID and it's unique across all types and objects. How this globally unique ID field is generated depends on the implementation. The globalIdField helper function generates this from the id field in object X and the type name X.
  4. In nodeDefinitions, retrieve local ID and type from global ID by using fromGlobalId helper function. Since, the id field in X was the _id field in MongoDB, you can use this local ID to perform DB operations. Convert from hex string to MongoDB ID type first.

Local ID assignment (step 2) must be broken in your implementation. Otherwise, ID of the same object would not be different on every reload.

Community
  • 1
  • 1
Ahmad Ferdous
  • 3,351
  • 16
  • 33
  • Thanks, you mentioned the key thing to understand this. I've read docs and many, many posts but it is never said clearly that global ID is formed from your given `string` + **returned `id` (it literally has to be `id`, can't be anything else)**. My problem was that I was using my own `id` and `_id` in database model and Relay was confused. – Solo Aug 09 '16 at 12:02