GraphQL Resolver Parent — Accessing the Parent Object in Resolver Chains
In this tutorial, you will learn about Graphql Resolver Parent. We cover key concepts, practical examples, and best practices to help you master this topic.
The resolver parent parameter (root) is the first argument in every resolver function, containing the parent object returned by the previous resolver in the chain, enabling nested field resolution.
What You'll Learn
- How the parent parameter flows through resolver chains
- Using parent data for child field resolution
- Transforming parent values
Why It Matters
Understanding the parent parameter is essential for building correct resolver chains. Without it, nested fields cannot access their parent context.
Code Examples
# Schema with nested resolvers
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
// Parent parameter in resolver chain
const resolvers = {
Query: {
// Parent is null for root queries
user: (parent, { id }, { db }) => {
console.log(parent); // null
return db.users.findById(id);
}
},
User: {
// Parent is the user object from the query resolver
posts: (parent, args, { db }) => {
console.log(parent.id); // "user-123"
return db.posts.findByAuthor(parent.id);
},
// Computed field using parent data
displayName: (parent) => {
return `${parent.firstName} ${parent.lastName}`;
}
},
Post: {
// Parent is the post object from User.posts resolver
author: (parent, args, { db }) => {
console.log(parent.authorId); // "user-123"
return db.users.findById(parent.authorId);
}
}
};
# Python parent parameter
import strawberry
@strawberry.type
class Post:
id: strawberry.ID
title: str
author_id: str
@strawberry.field
async def author(self) -> 'User':
# self is the parent post object
return await get_user(self.author_id)
@strawberry.type
class User:
id: strawberry.ID
name: str
@strawberry.field
async def posts(self) -> list[Post]:
# self is the parent user object
return await get_posts_by_user(self.id)
Common Mistakes
1. Expecting Parent to Be Populated for Root Fields
Root Query and Mutation resolvers have null parent. Handle this case.
2. Modifying the Parent Object
Do not mutate the parent object. Create new objects for transformed data.
3. Not Using Parent Data Efficiently
Access parent.id for database queries instead of re-fetching the parent.
4. Confusing Parent with Context
Parent is the previous resolver's return value. Context is shared across all resolvers.
5. Returning Wrong Types from Parent Resolvers
The parent resolver must return data that child resolvers expect.
Practice Questions
- What is the parent parameter in a resolver?
- What is the parent value for root Query resolvers?
- How do you access the parent's field values?
- Can you modify the parent object?
- How does parent flow through list fields?
Answers:
- The return value from the previous resolver in the chain.
- null (or undefined).
- Using parent.fieldName in the resolver.
- No, treat parent as read-only to avoid side effects.
- Each item in the list becomes the parent for child resolvers.
Challenge: Build a resolver chain with four levels: Query.user -> User.posts -> Post.comments -> Comment.author. Trace how the parent parameter flows at each level.
FAQ
Mini Project
Build a resolver chain for an order management system: Query.orders -> Order.items -> Item.product -> Product.supplier. Include computed fields that use parent data and handle null parent cases.
What's Next
Learn about resolver context for authentication and shared state, then explore mutation return types for mutation payloads.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro