I just use apollo to call api graph QL for some days
I just have a simple question
how can I pass an array like a variable to mutation
in my code, line 7, i want to pass "waypoints" array to mutation.
Please!!!
const GET_QUOTATION = gql`
query($date: String!) {
getQuotation(
input: {
pickupTime: $date
serviceType: CAR
waypoints: [
{
type: PICKUP
address1: "Anson Road, #23-01"
address2: "079906"
location: {lat: "1.307274", lng: "103.883998"}
name: "Jack"
phone: "82187877"
}
]
}
) {
delivery {
provider
price
}
poolWindow {
price
window
}
}
}
`;
const [getQuotation, quotationData] = useLazyQuery(GET_QUOTATION, {
onCompleted() {
console.log('-> success');
},
onError() {
console.log('-> error');
},
variables: {
date: '2021-03-12T18:54:00Z',
},
});
Related
I am trying to set up GraphQL Subscriptions but it seems to get connected to the backend but it's not pushing any updates.
On frontend, I am using Nuxt 2 and that's how I am trying to get it working:
That's my test query
export const pendingInquiresSubscription = () => {
return gql`
subscription PendingInquires {
countPendingInquires {
amount
}
}`
}
My smartQuery on the page component
apollo: {
$subscribe: {
pendingInquires: {
query: pendingInquiresSubscription(),
result({ data, loading }) {
this.loading = loading;
console.log(data)
},
error(err) {
this.$notify({ message: `Что-то пошло не так пытаясь обновить количество новый запросов: ${err.message}`, type: 'error' })
},
}
}
},
Backend:
my pubsub
import { RedisPubSub } from 'graphql-redis-subscriptions';
import Redis from 'ioredis';
const REDIS_DOMAIN_NAME = '127.0.0.1'
const PORT_NUMBER = 6379
const options = {
host: REDIS_DOMAIN_NAME,
port: PORT_NUMBER,
retryStrategy: (times: any) => {
return Math.min(times * 50, 2000);
}
}
export const pubsub = new RedisPubSub({
publisher: new Redis(options),
subscriber: new Redis(options)
})
My Schema:
extend type Subscription {
countPendingInquires: PendingInquires!
}
type PendingInquires {
amount: Int!
}
My resolver
...
Subscription: {
countPendingInquires: {
subscribe: () => pubsub.asyncIterator(['countPendingInquires'])
},
},
...
That's the way I am trying to push the event:
pubsub.publish('countPendingInquires', {
PendingInquires: {
amount: await TelegramInguireModel.find({ }).countDocuments()
}
})
And I also wonder if there is any built-in way to set the initial state for subscriptions.
The issue was in the way I was trying to push the event
The correct way of pushing is like this:
pubsub.publish('countPendingInquires', {
countPendingInquires: { // <- here was the issue
amount: await TelegramInquireModel.find({ }).countDocuments()
}
)
I've just set wrong subscription name
I'm using expressjs and apollo-server-express. I'm trying to set up a query in graphql to return a product from my database. The problem is that the results never show up in graphql, but when I console log resultsArr the results show up fine. Just to note the resultsArr is an array of objects.
Express:
const typeDefs = gql`
type Search {
brand: String
title: String
url: String
thumbnail: String
}
type Query {
results(query: String!): Search
}
`;
const resolvers = {
Query: {
results: (parent, args) => {
const queries = [
{
indexName: 'products',
query: args.query,
params: {
hitsPerPage: 1,
},
},
//
];
return AlgoliaClient.multipleQueries(queries).then(({ results }) => {
// Store Results
const resultsArr = [];
results.forEach((item) => {
resultsArr.push(item.hits[0]);
});
// console logging this shows the products
return resultsArr;
});
},
},
};
and my query the graphql playground is:
query Search {
results(query: "Test product") {
title
}
}
The problem is when I console log resultsArr the products show up no problem, however when it try it though the query I get:
{
"data": {
"results": {
"title": null
}
}
}
In my vue screen I'd like to use one apollo graphql I've defined for two properties. As far as I understand the name of the property must match a name of the attribute in the returned json structure.
I naivly tried to use the queries for two properties but it throws an error for the second one.
...
data() {
return {
userId: number,
user: null as User | null,
previousUserId: number,
previousUser: null as User | null
};
},
...
apollo {
user: {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
}
},
previousUser: {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
export const READ_ONE_USER = gql(`
query user($userId: Int!) { user(userId: $userId)
{
id
firstName
lastName
email
}
}
`);
I expected no problems but I get "Missing previousUser attribute on result {user: ...}"
Daniel's solution didn't work out for me, I still got the same error message.
But there's another way to do it, you can provide an update function to tell apollo how to extract the result out of the data read from the server:
apollo {
user: {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
}
},
previousUser: {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
update(data) {
return data.user;
}
}
This is documented at https://github.com/vuejs/vue-apollo/blob/v4/packages/docs/src/api/smart-query.md#options
As shown in the docs, you can manually add smart queries inside the created hook:
created () {
this.$apollo.addSmartQuery('user', {
query: READ_ONE_USER,
variables() {
return {
userId: this.userId
};
},
})
this.$apollo.addSmartQuery('previousUser', {
query: READ_ONE_USER,
variables() {
return {
userId: this.previousUserId
};
},
})
}
I would like to create a checkout object via the GraphQL API provided by the Saleor eCommerce platform.
According to the gql playground there is a mutation to do so that takes a CheckoutCreateInput object as it's argument.
Here is an example mutation that works fine within the playground.
Here is the current code that I have tried (I am doing this within a vuex action)
export const actions = {
addToCart({ commit, dispatch }, cartItem) {
const currentCartItems = this.state.cartItems
// Check to see if we already have a checkout object
if (this.state.checkoutId !== '') {
// Create a new checkout ID
console.log('creating new checkout object')
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: { quantity: 10, variantId: 'UHJvZHVjdFZhcmlhbnQ6NQ==' },
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log(data)
})
} catch (e) {
console.log(e)
}
} else {
console.log('checkout id already set')
}
// TODO: Check to see if the cart already contains the current Cart Item
commit('ADD_CART_ITEM', cartItem)
}
and here is the CREATE_CART_MUTATION:
import gql from 'graphql-tag'
export const CREATE_CART_MUTATION = gql`
mutation($checkoutInput: CheckoutCreateInput!) {
checkoutCreate(input: $checkoutInput) {
checkout {
id
created
lastChange
lines {
id
variant {
id
name
}
quantity
totalPrice {
gross {
localized
}
net {
localized
}
}
}
totalPrice {
gross {
localized
}
net {
localized
}
}
}
}
}
`
On the server this comes back with the following error:
graphql.error.base.GraphQLError: Variable "$checkoutInput" got invalid value {"email": "test#test.com", "lines": {"quantity": 10, "variantId": "UHJvZHVjdFZhcmlhbnQ6NQ=="}}.
In field "lines": In element #0: Expected "CheckoutLineInput", found not an object.
Looks like I was most of the way there, I was just passing a single lines object rather than an array of them. The correct code is as follows:
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: [
{ quantity: cartItem.quantity, variantId: cartItem.variantId }
],
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log('mutation done!')
commit('SET_CHECKOUT_OBJECT', data.checkoutCreate.checkout)
})
} catch (e) {
console.log('error:')
console.log(e)
}
I am using vue-head in website because of I have to pass the name of the program to the html head, and the inf. it is coming from an API, so I make the request but every time I try to pass the name it send me error this the code:
export default {
data: () => ({
errors: [],
programs: [],
firstVideo: {},
vidProgram: {}
}),
},
created() {
//do something after creating vue instance
this.api = new ApiCanal({})
this.getProgram()
},
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.firstVideo = response.data[0]
this.vidProgram = response.data[0]['program']
})
.catch(error => {
this.errors = error
});
}
},
head: {
//this is the inf. for the head
title: {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
}
}
}
I will really appreciate if you can help me with this issue
If you want to use properties of your Vue object/component in the title there, you need to make it a function, as currently this refers to the object creating your Vue component (probably the global window object).
head: {
title: function() {
return {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
};
}
}