Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is nodeInterface, nodeField and nodeDefinitions in Relay?

Tags:

I am currently doing the facebook relayjs tutorial and I need help understanding this part of the tutorial, it states

Next, let's define a node interface and type. We need only provide a way for Relay to map from an object to the GraphQL type associated with that object, and from a global ID to the object it points to

const {nodeInterface, nodeField} = nodeDefinitions(
  (globalId) => {
    const {type, id} = fromGlobalId(globalId);
    if (type === 'Game') { 
      return getGame(id);
    } else if (type === 'HidingSpot') {
      return getHidingSpot(id);
    } else {
      return null;
    }
  },
  (obj) => {
    if (obj instanceof Game) {
      return gameType;
    } else if (obj instanceof HidingSpot) {
      return hidingSpotType;
    } else {
      return null;
    }
  }
);

On the first argument on nodeDefinition,where did it get its' globalId? is Game and HidingSpot a name on the GraphQLSchema? What does this 'const {type, id} = fromGlobalId(globalId);' do? and also what is the 2nd argument? I need help understanding nodeDefinitions, somehow I can't find nodeDefinitions on the official documentation. Thank you.

like image 898
gpbaculio Avatar asked Mar 03 '17 10:03

gpbaculio


2 Answers

If you were writing a GraphQL server without Relay, you'd define a number of entry points on the Query type, eg:

type Query {
  picture(id: Int!): Picture
  user(id: Int!): User
  ...etc
}

So when you want to get a User, you can easily get it because user is available as an entry point into the graph. When you build a query for your page/screen, it'll typically be several levels deep, you might go user -> followers -> pictures.

Sometimes you want to be able to refetch only part of your query, perhaps you're paginating over a connection, or you've run a mutation. What Relay's Node interface does is give you a standard way to fetch any type that implements it via a globally unique ID. Relay is capable of recognising such nodes in its queries, and will use them if possible to make refetching and paginating more efficient. We add the node type to the root Query type:

type Query {
  picture(id: Int!): Picture
  user(id: Int!): User
  ...etc
  node(id: ID!): Node
}

Now for nodeDefinitions. Essentially this function lets us define two things:

  1. How to return an object given its globalId.
  2. How to return a type given an object.

The first is used to take the ID argument of the node field and use it to resolve an object. The second allows your GraphQL server to work out which type of object was returned - this is necessary in order for us to be able to define fragments on specific types when querying node, so that we can actually get the data we want. Without this, we couldn't be able to successfully execute a query such as this:

query Test {
  node(id: 'something') {
     ...fragment on Picture {
       url
     }
     ...fragment on User {
       username
     }
  }
}
like image 124
Andrew Ingram Avatar answered Sep 23 '22 10:09

Andrew Ingram


Relay uses global object identification, which means, in my understanding, if your application ever try to search for an object. In your example, try to look for a game, or try to look for a hidingSpot. Relay will try to fetches objects in the standard node interface. i.e. find by {id: 123} of the Game, or find by {id:abc} of the hidingSpot. If your schema (Game, HidingSpot) doesn't set up the node interface, Relay will not be able to fetch an object.

Therefore, if your application requires a search in a "Game", in the schema, you need to define the node interfaces.

By using graphql-relay helper, use nodeDefinitions function only once in your application to basically map globally defined Ids into actual data objects and their GraphQL types.

The first argument receives the globalId, we map the globalId into its corresponding data object. And the globalId can actually be used to read the type of the object using fromGlobalId function.

The second function receives the result object and Relay uses that to map an object to its GraphQL data type. So if the object is an instance of Game, it will return gameType, etc.

Hope it will help you understand. I am on my way learning, too.

like image 35
Yumiko Avatar answered Sep 23 '22 10:09

Yumiko