0

I'm trying to publish the newly added post, but the fields author and voteCount which are custom fields and reference another type were not being publish so that I got undefined on those fields.

My schema:

type Post {
    id: ID!
    title: String!
    content: String
    voteCount: Int!
    author: User!
    votes: [Vote!]!
    createdAt: Date!
    updatedAt: Date!
  }
type Subscription {
    Post(filter: PostSubscriptionFilter): PostSubscriptionPayload
  }
  input PostSubscriptionFilter {
    mutation_in: [_ModelMutationType!]
  }
  type PostSubscriptionPayload {
    mutation: _ModelMutationType!
    node: Post
  }
  enum _ModelMutationType {
    CREATED
    UPDATED
    DELETED
  }

Resolver

Mutation: {
    addPost: async (
      root,
      { title, content },
      { ValidationError, models: { Post }, user },
    ) => {
      if (!user) {
        throw new ValidationError('unauthorized');
      }
      const post = new Post({
        title,
        content,
        author: user.id,
      });
      await post.save();
      pubsub.publish('Post', { Post: { mutation: 'CREATED', node: post } });
      return post;
    },
},
Subscription: {
    Post: {
      subscribe: () => pubsub.asyncIterator('Post'),
    },
  },
Post: {
    // eslint-disable-next-line no-underscore-dangle
    id: root => root.id || root._id,
    author: async ({ author }, data, { dataLoaders: { userLoader } }) => {
      const postAuthor = await userLoader.load(author);
      return postAuthor;
    },
    voteCount: async ({ _id }, data, { models: { Vote } }) => {
      const voteCount = await Vote.find({ post: _id }).count();
      return voteCount || 0;
    },
    votes: async ({ _id }, data, { models: { Vote } }) => {
      const postVotes = await Vote.find({ post: _id });
      return postVotes || [];
    },
  },

And the subscription in React client:

componentWillMount() {
    this.subscribeToNewPosts();
  }
subscribeToNewPosts() {
    this.props.allPostsQuery.subscribeToMore({
      document: gql`
        subscription {
          Post(filter: { mutation_in: [CREATED] }) {
            node {
              id
              title
              content
              updatedAt
              voteCount
            }
          }
        }
      `,
      updateQuery: (previous, { subscriptionData }) => {
        // const result = Object.assign({}, previous, {
        //   allPosts: [subscriptionData.data.Post.node, ...previous.allPosts],
        // });
        // return result;
        console.log(subscriptionData);
        return previous;
      },
    });
  }

The field voteCount is undefined: enter image description here

While using queries or mutations, it get published normally, what should I do? Thank you.

4

1 回答 1

1

The error you're seeing doesn't necessarily mean that voteCount is null -- rather it means you're trying to destructure an undefined value instead of an object. The path tells you this error occurred while attempting to resolve voteCount. You utilize destructuring within your resolve function in two places -- once with the root object and again with context. There should be a root object with you to work with, so I imagine the issue is with context.

When you set up context for a typical GraphQL server, you do so by utilizing middleware (like graphqlExpress) to essentially inject it into the request you're making. When you use subscriptions, everything is done over websockets, so the middleware is never hit and your context is therefore null.

To get around this, I think you'll need to inject the same context into your subscriptions -- you can see an example of how to do that here.

于 2017-08-19T13:31:52.347 回答