0
0
GraphqlHow-ToBeginner · 4 min read

How to Implement a Follow System in GraphQL

To implement a follow system in GraphQL, define a User type with a list of followers and following users. Create mutations to follow and unfollow users, and queries to fetch these relationships. This setup allows clients to manage and retrieve follow data efficiently.
📐

Syntax

The follow system uses a User type with fields for followers and following. Mutations like followUser and unfollowUser update these lists. Queries fetch user data including their followers and following.

  • type User: Defines user fields and relationships.
  • type Mutation: Defines actions to follow/unfollow.
  • type Query: Fetches user and their follow data.
graphql
type User {
  id: ID!
  username: String!
  followers: [User!]!
  following: [User!]!
}

type Mutation {
  followUser(userId: ID!): User!
  unfollowUser(userId: ID!): User!
}

type Query {
  user(id: ID!): User
  users: [User!]!
}
💻

Example

This example shows a simple GraphQL schema and resolver logic for a follow system using an in-memory user list. It demonstrates how to follow and unfollow users and query their followers and following.

javascript
const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type User {
    id: ID!
    username: String!
    followers: [User!]!
    following: [User!]!
  }

  type Mutation {
    followUser(userId: ID!): User!
    unfollowUser(userId: ID!): User!
  }

  type Query {
    user(id: ID!): User
    users: [User!]!
  }
`;

const users = [
  { id: '1', username: 'Alice', followers: [], following: [] },
  { id: '2', username: 'Bob', followers: [], following: [] },
  { id: '3', username: 'Charlie', followers: [], following: [] }
];

const resolvers = {
  User: {
    followers(user) {
      return users.filter(u => user.followers.includes(u.id));
    },
    following(user) {
      return users.filter(u => user.following.includes(u.id));
    }
  },
  Query: {
    user(_, { id }) {
      return users.find(u => u.id === id);
    },
    users() {
      return users;
    }
  },
  Mutation: {
    followUser(_, { userId }, { currentUserId = '1' }) {
      const currentUser = users.find(u => u.id === currentUserId);
      const userToFollow = users.find(u => u.id === userId);
      if (!userToFollow) throw new Error('User not found');
      if (!currentUser.following.includes(userId)) {
        currentUser.following.push(userId);
        userToFollow.followers.push(currentUserId);
      }
      return currentUser;
    },
    unfollowUser(_, { userId }, { currentUserId = '1' }) {
      const currentUser = users.find(u => u.id === currentUserId);
      const userToUnfollow = users.find(u => u.id === userId);
      if (!userToUnfollow) throw new Error('User not found');
      currentUser.following = currentUser.following.filter(id => id !== userId);
      userToUnfollow.followers = userToUnfollow.followers.filter(id => id !== currentUserId);
      return currentUser;
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});
Output
Server ready at http://localhost:4000/
⚠️

Common Pitfalls

Common mistakes include not updating both users' follower and following lists, causing inconsistent data. Forgetting to check if a user already follows another can lead to duplicates. Also, not handling errors when users don't exist can crash the system.

javascript
/* Wrong: Only updating one side */
currentUser.following.push(userId);
// Missing: userToFollow.followers.push(currentUserId);

/* Right: Update both sides */
if (!currentUser.following.includes(userId)) {
  currentUser.following.push(userId);
  userToFollow.followers.push(currentUserId);
}
📊

Quick Reference

  • Define User type with followers and following as lists of Users.
  • Create Mutations to follow and unfollow users, updating both sides.
  • Use Queries to fetch users and their follow relationships.
  • Validate inputs and prevent duplicates.

Key Takeaways

Define User type with followers and following fields as lists of Users.
Create mutations to follow and unfollow users, updating both users' lists.
Always check if the follow relationship already exists to avoid duplicates.
Handle errors when users do not exist to keep the system stable.
Use queries to retrieve user follow data efficiently.