I would like to send an array of object in a graphQL queries. But I don't have any idea how to type the pointer in the query $gallery: where Type will be a simple datastructure like a class or dictionnary.
apollo_client.mutate({mutation: gql`
mutation m(
$title: String!, $gallery:<Type?>){
mutatePmaGallery(pmaData:
{title: $title, gallery: $gallery}) {
pma{
id
}
}
}`,
variables: {
title: _this.state.title,
gallery: {<Type?>}
})
You first need to define an input type according to your gallery structure :
input GalleryType {
id:ID!
name: String!
}
Then you can simply do this:
apollo_client.mutate({mutation: gql`
mutation m(
$title: String!, $gallery:[GalleryType!]!){ //changed part
mutatePmaGallery(pmaData:
{title: $title, gallery: $gallery}) {
pma{
id
}
}
}`,
variables: {
title: _this.state.title,
gallery: {<Type?>}
})
Related
Schema:
type Mutation {
removeProduct(id: String!): Product
}
type Product {
id: ID!
name: String!
slug: String!
description: String!
price: Float!
image: String!
ingredients: [String]
addOns: [String]
}
resolver:
exports.Mutation = {
removeProduct: async (parent, { id }, { Product }) => {
const deletedProduct = await Product.deleteOne({ id });
return deletedProduct;
},
};
query:
mutation{
removeProduct(id:"b55572b9-eb4d-46ea-a82f-f01cb0ba3993")
{
id
name
}
}
I need to remove a product from the db, but while deleting it, the response from graphql shows that "message": "Cannot return null for non-nullable field Product.name.",
It maybe because the product is deleted and nothing is returned because there is no product in db.
How do I write a query to delete a product ?
Note that it deletes the product from the db, but shows error in graphql response.
On the server I built a schema where I used and input type to obtain the ability to pass an array of objects. I've done this in a couple of places but this is by far the most simple one:
export default gql`
input SkillInput{
skill: String!
}
extend type Mutation {
createSkill(input: [SkillInput]): [Skill]!
}
type Skill {
id: ID!
skill: String!
created_at: DateTime!
}
`;
On the frontend, I'm able to execute the mutation with said array of objects just fine. The issue comes when I try to incorporate optimistic response.
This isthe mutation in question:
this.$apollo
.mutate({
mutation: CREATE_SKILL_MUTATION,
variables: { input: skillArrOfObj },
optimisticResponse: {
__typename: "Mutation",
createSkill: skillArrOfObj.map(entry => ({
__typename: "Skill",
id: -1,
skill: entry.skill
}))
},
update: (store, { data: { createSkill } }) => {
const data = store.readQuery({
query: SKILLS_QUERY
});
console.log(createSkill);
data.skills.push(...createSkill);
store.writeQuery({
query: SKILLS_QUERY,
data
});
}
})
I've tried to add to each entry of skillArrOfObj the __typename and id, however the mutation fails.
Another thing to mention is that update runs twice and the log on createSkill yields two different results on update:
First run
{__typename: "Skill", id: -1, skillObj: Array(2)}
id: -1
skillObj: (2) [{…}, {…}]
__typename: "Skill"
Second run shows an array of just the id and the __typename with no skill attribute
Is there a special __typename needed for arrays? Or something I need to do before running the mutation?
After running into an issue trying things out on my own, I tried the example from the docs and I ran into a similar issue, is the doc wrong, or am I doing something stupid?
The example I am trying to execute is the one from this page: https://www.apollographql.com/docs/apollo-server/federation/introduction/
The relevant piece of code is:
const server = new ApolloServer({
schema: buildFederatedSchema([{
typeDefs: gql`
extend type Query {
me: User
}
type User #key(fields: "id") {
id: ID!
username: String!
}
`,
resolvers: [],
}, {
typeDefs: gql`
extend type Query {
topProducts(first: Int = 5): [Product]
}
type Product #key(fields: "upc") {
upc: String!
name: String!
price: Int
}
`,
resolvers: [],
}, {
typeDefs: gql`
type Review {
body: String
author: User #provides(fields: "username")
product: Product
}
extend type User #key(fields: "id") {
id: ID! #external
reviews: [Review]
}
extend type Product #key(fields: "upc") {
upc: String! #external
reviews: [Review]
}
`,
resolvers: [],
}]),
context: ({ req }) => ({ user: req.user }),
})
Note that I left the resolvers empty on purpose, I am just trying to compile the schema.
Here is the error I get:
GraphQLSchemaValidationError: Field "User.id" can only be defined once. Field "Product.upc" can only be defined once.
Can someone help me out with that?
I have used express-graphql and there i used to do something like this.
const SubCategoryType = new ObjectType({
name: 'SubCategory',
fields: () => ({
id: { type: IDType },
name: { type: StringType },
category: {
type: CategoryType,
resolve: parentValue => getCategoryBySubCategory(parentValue.id)
},
products: {
type: List(ProductType),
resolve: parentValue => getProductsBySubCategory(parentValue.id)
}
})
});
Here I have multiple resolvers, id and name are fetched directly from the result. and the category and products have there own database operation. and so on.
Now I am working on apollo-server and I can't find a way to replicate this.
for example I have a type
type Test {
something: String
yo: String
comment: Comment
}
type Comment {
text: String
createdAt: String
author: User
}
and in my resolver I want to split it up, for example something like this
text: {
something: 'value',
yo: 'value',
comment: getComments();
}
NOTE: this is just a representation of what I need.
You can add type-specific resolvers to handle specific fields. Let's say you have the following schema (based on your example):
type Query {
getTest: Test
}
type Test {
id: Int!
something: String
yo: String
comment: Comment
}
type Comment {
id: Int!
text: String
createdAt: String
author: User
}
type User {
id: Int!
name: String
email: String
}
Let's also assume you have the following DB methods:
getTest() returns an object with fields something, yo and
commentId
getComment(id) returns an object with fields id, text, createdAt and userId
getUser(id) returns an object with fields id, name and email
Your resolver will be something like the following:
const resolver = {
// root Query resolver
Query: {
getTest: (root, args, ctx, info) => getTest()
},
// Test resolver
Test: {
// resolves field 'comment' on Test
// the 'parent' arg contains the result from the parent resolver (here, getTest on root)
comment: (parent, args, ctx, info) => getComment(parent.commentId)
},
// Comment resolver
Comment: {
// resolves field 'author' on Comment
// the 'parent' arg contains the result from the parent resolver (here, comment on Test)
author: (parent, args, ctx, info) => getUser(parent.userId)
},
}
Hope this helps.
I have a Graphql Mutation like this:
gql query:
mutation UpdateMother($mother_id: ID!, $child_name: String!) {
updateMother(
mother: {
id: $id
child: {
name: $child_name
}
}
)
}
It works good, but I need to use $child.name instead of $child_name. Is this possible?
You should be able to call this mutation like
mutate({
variables: {
mother_id: mother.id,
child_name: child.name
}
})
.then(() => {})
.catch(() => {})
Also note that you're defining $mother_id as an input, and using $id in the 4th line. You should be using something like:
mutation UpdateMother($mother_id: ID!, $child_name: String!) {
updateMother(
mother: {
id: $mother_id
child: {
name: $child_name
}
}
)
}