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
followersandfollowingas 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.