Search code examples
javascriptgraphqlgraphql-jsrelayexpress-graphql

GraphQL Connections


I have this relationship btw a user and its memberships. The memberships field is a connection between a user and multiple memberships.

const MembershipType = new GraphQLObjectType({
  name: 'Membership',
  interfaces: [nodeInterface],

  fields: {
    id: globalIdField(),

    user: {
      type: new GraphQLNonNull(UserType),
      resolve(parent, args, ctx: Context) {
        return ctx.userById.load(parent.user_id);
      },
    },

    role: {
      type: new GraphQLNonNull(GraphQLString),
    },

    team: {
      type: GraphQLString,
    },

    createdAt: {
      type: new GraphQLNonNull(GraphQLString),
      resolve(parent) {
        return parent.created_at;
      },
    },

    updatedAt: {
      type: new GraphQLNonNull(GraphQLString),
      resolve(parent) {
        return parent.updated_at;
      },
    },
  },
});

export default MembershipType;


const UserType = new GraphQLObjectType({
  name: 'User',
  interfaces: [nodeInterface],

  fields: {
    id: globalIdField(),

    firstName: {
      type: GraphQLString,
      resolve(parent) {
        return parent.first_name;
      },
    },

    lastName: {
      type: GraphQLString,
      resolve(parent) {
        return parent.last_name;
      },
    },

    email: {
      type: GraphQLString,
      resolve(parent) {
        return parent.email;
      },
    },

    memberships: {
      type: new GraphQLList(MembershipType),
      resolve(parent, args, ctx: Content) {
        return ctx.membershipsByUserId.load(parent.id);
      },
    },

    membershipsCount: {
      type: new GraphQLNonNull(GraphQLInt),
      resolve(parent, args, ctx: Context) {
        return ctx.userMembershipsCount.load(parent.id);
      },
    },
  },
});

export default UserType;

The issue here is that I have this error where user field in MembershipType causes an error

Blockquote /Users/nizarayari/Arise/arise-auth/node_modules/graphql/jsutils/invariant.js:19 throw new Error(message); ^ Error: Expected undefined to be a GraphQL nullable type. at invariant (/Users/nizarayari/Arise/arise-auth/node_modules/graphql/jsutils/invariant.js:19:11) at assertNullableType (/Users/nizarayari/Arise/arise-auth/node_modules/graphql/type/definition.js:261:51) at new GraphQLNonNull (/Users/nizarayari/Arise/arise-auth/node_modules/graphql/type/wrappers.js:79:54) at Object. (/Users/nizarayari/Arise/arise-auth/src/schema/membership/MembershipType.js:25:13) at Module._compile (module.js:624:30) at Object.Module._extensions..js (module.js:635:10) at Module.load (module.js:545:32) at tryModuleLoad (module.js:508:12) at Function.Module._load (module.js:500:3) at Module.require (module.js:568:17) at require (internal/module.js:11:18) at Object. (/Users/nizarayari/Arise/arise-auth/src/schema/user/UserType.js:19:1) at Module._compile (module.js:624:30) at Object.Module._extensions..js (module.js:635:10) at Module.load (module.js:545:32) at tryModuleLoad (module.js:508:12)

Here is my query for user

import UserType from './UserType';
import type Context from '../../Context';

const me = {
  type: UserType,
  resolve(root: any, args: any, ctx: Context) {
    return ctx.user && ctx.userById.load(ctx.user.id);
  },
};

export default {
  me,
};

No queries for memberships just mutation


Solution

  • Are both fields in the same js file? You have export default on both Memberships and UserType in what looks like the same js file.

    You can only use export default on one field in each file.

    Once you separate the two fields, since Membership depends on UserType, the trick is to use a function that returns the fields object in Membership

    const MembershipType = new GraphQLObjectType({
      name: 'Membership',
      interfaces: [nodeInterface],
      fields: () => ({
        id: globalIdField(),
        ...
      })
    });
    

    instead of:

    const MembershipType = new GraphQLObjectType({
      name: 'Membership',
      interfaces: [nodeInterface],
      fields: {
        id: globalIdField(),
        ...
      }
    });