Apollo Graphql query in React with input values - reactjs

I'm having trouble to make a query in React with Apollo. I know how to do it in the playground and basic queries in React but I can't figure out how to pass dynamically the values for an input inside the query. The query should be like this. This works on playground.
getCityByName(name: "London", country: "GB", config:{units:metric, lang: sp}) {
id
name
weather {
summary {
description
}
temperature {
actual
}
}
}
The units and lang are enum. In React I could only pass the name and country dinamically but not the config options, I only get errors and I've tried so many different syntax.
The only way I can is hardcoding like this:
const GET_DATA = gql`
query getCity($name: String!, $country: String) {
getCityByName(
name: $name
country: $country
config: { units: metric, lang: sp }
) {
id
name
country
weather {
summary {
description
}
temperature {
actual
}
}
}
}
`;
const { loading, data, error } = useQuery(GET_DATA, {
variables: {
name: 'London',
country: 'GB',
},
});
How can I make units and lang dynamic?

Related

use graphql query and mutation in same file

const QUERIES = gql`
query {
getGrades {
grade_info
id
}
getSubjects {
id
subject_info
}
getSchools {
school_name
id
}
}
`;
const MUTATIONS = gql`
mutation {
createTeacher(
first_name: ${firstName}
last_name: ${lastName}
phone: "${number}
email: ${email}
subjectRef: ["6287323efe0b204eee241cc5"]
gradeRef: ["62872b8b0023e0dcc9c5a703"]
schoolRef: "62ab59edde044d104f10e5a9"
) {
id
first_name
last_name
phone
email
email_verified
approved
number_verified
}
}
`;
const { loading, error, data } = useQuery(QUERIES);
const [mutateFunction, { data, loading, error }] = useMutation(MUTATIONS);
Here is my graphql query using in react .
But my data variable conflicting in query and mutation
How to handle the situation ?
Please take a look .
If am changing data to something else it is not working.
You are using a destructuring assignment in order to extract the fields data, error, loading from the response of useQuery and useMutation.
The destructuring assingment operator allows renaming the variables (please find better variable names than I used as an example ;-) )
Example:
const { loading: loadingQueries, error: errorQueries, data: dataQueries } = useQuery(QUERIES);
//use
console.log(loadingQueries);
The same can be applied for useMutation.

Nested graphql query

I am pretty new with graphql , I don't know how to apply this filter.
following is schema
const GET_TICKETS = gql`
query Ticket($filter: String) {
tickets(filter: $filter) {
id
title
firstname
lastname
gender
contactnumber
email
address
pincode
location
emergency_type
priority
descriptionof_assistance
date_created
status
work_items {
id
status
service
volunteers {
volunteer_id
volunteer_name
status_of_acceptance
}
}
}
}
`;
I want to fetch all tickets where workitems contain given volunteer
fetch tickets where volunteer in workitems.volunteers ....something like this
When you use useQuery There is an optional second parameter or useLazyQuery on the function trigger.
Example from the official documentation.
useQuery
const { loading, error, data } = useQuery(GET_DOG_PHOTO, {
variables: { breed },
});
So on your case it should be
const { loading, error, data } = useQuery(GET_TICKETS, {
variables: { filter: "the filter value" },
});
and on useLazyQuery will look like this:
const [getTickets, { loading, error, data }] = useLazyQuery(GET_TICKETS);
//..... somewhere else
getTickets({variables: {filter: "filter value"}})
reference: https://www.apollographql.com/docs/react/data/queries/

getting different data from db than in GraphiQL

I'm new to graphQL and mongoDB and I'm trying to make it work in my project. The problem is with data from query that in GraphiQL is completely different than data from the same query inside my client side. Here's my setup of schema:
const graphql = require('graphql');
const _ = require('lodash');
const Item = require('../models/item');
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql;
const ItemType = new GraphQLObjectType({
name: 'Item',
fields: () => ({
name: {
type: GraphQLString
},
id: {
type: GraphQLID
},
description: {
type: GraphQLString
},
price: {
type: GraphQLInt
},
image: {
type: GraphQLString
},
category: {
type: GraphQLString
}
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
item: {
type: ItemType,
args: {
id: {
type: GraphQLID
}
},
resolve(parent, args) {
// code to get data from db / other source
return Item.findById(args.id);
}
},
items: {
type: new GraphQLList(ItemType),
resolve(parent, args) {
return Item.find({})
}
}
}
});
When im doing a query from graphiQL of all the itemes and data i'm receiving is the "right one". It looks like this:
When i'm doing the same exact query from the front-end like that:
import { gql } from "apollo-boost";
const getItemsQuery = gql`
{
items {
name
id
description
price
image
category
}
}
`;
export { getItemsQuery };
The data looks like this:
It looks like it is repeating first item over and over and i can't see why. DB is also showing right items. My server side code can be found here: https://github.com/KamilStaszewski/shoppy/tree/adding_graphQL/server
From the docs:
The InMemoryCache normalizes your data before saving it to the store by splitting the result into individual objects, creating a unique identifier for each object, and storing those objects in a flattened data structure. By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object.
In other words, Apollo will use both __typename and id to create a cache key for each Item you fetch. This key is used to fetch the appropriate item from the cache. The problem is that your items are returning null for their id. This results in each item being written with the same key. As a result, when your query result is returned from the cache, it looks up the same key for each item in your items array.
To fix this issue, you need to ensure that your API returns a value for id. I haven't worked with mongoose that much, but I think since mongoose adds an id field for you automatically based on the _id, it should be sufficient to just remove the id from your mongoose model (not your GraphQL type). Alternatively, you could try adding a resolve function to your id field in the GraphQL type:
resolve: (item) => item._id.toString()

readQuery not working with pagination in Apollo & GraphQL app

I've got the following setup for my app. I have a LinkList component that renders a list of Link components. Then I also have a CreateLink component to create new links. Both are rendered under different routes with react-router:
<Switch>
<Route exact path='/create' component={CreateLink}/>
<Route exact path='/:page' component={LinkList}/>
</Switch>
The Link type in my GraphQL schema looks as follows:
type Link implements Node {
url: String!
postedBy: User! #relation(name: "UsersLinks")
votes: [Vote!]! #relation(name: "VotesOnLink")
comments: [Comment!]! #relation(name: "CommentsOnLink")
}
I'm using Apollo Client and want to use the imperative store API to update the list after new Link was created in the CreateLink component.
await this.props.createLinkMutation({
variables: {
description,
url,
postedById
},
update: (store, { data: { createLink } }) => {
const data = store.readQuery({ query: ALL_LINKS_QUERY }) // ERROR
console.log(`data: `, data)
}
})
The problem is that store.readQuery(...) throws an error:
proxyConsole.js:56 Error: Can't find field allLinks({}) on object (ROOT_QUERY) {
"allLinks({\"first\":2,\"skip\":10})": [
{
"type": "id",
"id": "Link:cj3ucdguyvzdq0131pzvn37as",
"generated": false
}
],
"_allLinksMeta": {
"type": "id",
"id": "$ROOT_QUERY._allLinksMeta",
"generated": true
}
}.
Here is how I am fetching the list of links in my LinkList component:
export const ALL_LINKS_QUERY = gql`
query AllLinksQuery($first: Int, $skip: Int) {
allLinks(first: $first, skip: $skip) {
id
url
description
createdAt
postedBy {
id
name
}
votes {
id
}
}
_allLinksMeta {
count
}
}
`
export default graphql(ALL_LINKS_QUERY, {
name: 'allLinksQuery',
options: (ownProps) => {
const { pathname } = ownProps.location
const page = parseInt(pathname.substring(1, pathname.length))
return {
variables: {
skip: (page - 1) * LINKS_PER_PAGE,
first: LINKS_PER_PAGE
},
fetchPolicy: 'network-only'
}
}
}) (LinkList)
I am guessing that the issue somehow has to do with my pagination approach, but I still don't know how to fix it. Can someone point me into the right direction here?
How to read a paginated list from the store depends on how you do the pagination. If you're using fetchMore, then all the data will be stored under the original keys of the query, which in this case I guess was fetched with { first: 2, skip: 0 }. That means in order to read the updated list from the store, you would have to use the same parameters, using { first: 2, skip: 0 } as variables.
PS: The reason Apollo does it this way is because it still allows you to relatively easily update a list via a mutation or update store. If each page was stored separately, it would be very complicated to insert an item in the middle or the beginning of the list, because all of the pages would potentially have to be shifted.
That said, we might introduce a new client-side directive called #connection(name: "ABC") which would let you explicitly specify under which key the connection is to be stored, instead of automatically storing it under the original variables. Happy to talk more about it if you want to open an issue on Apollo Client.

How to updateQueries when the Query contain edges and node with Apollo?

I use react-apollo on my React application for request a GraphQL API. I want to add an item and update my query after this add.
The item is added correctly but I can't update my query. I have to refresh my page to see my new item. I follow this guide.
This is my query:
export const allCodeReviews = gql`
query allCodeReviews {
allCodeReviews {
edges {
node {
id
reference
reviewer
revisionDate
redmineUrl
flow {
id
name
}
}
}
}
}
and this is my mutation which add my new item:
this.props.mutate({
variables: {
"reviewer": "john",
"revisionDate": "2016-11-11",
"flow": "foo",
"redmineUrl": "foo.com",
"reference": "#bar"
},
updateQueries: {
allCodeReviews: (prev, {mutationResult}) => {
const addedReview = mutationResult.data.addCodeReview.codeReview;
console.log(addedReview);
console.log(prev);
return update(prev, {
allCodeReviews: {
edges: {
$unshift: [addedReview]
}
}
});
}
}
});
How to update this query correctly?
I think you should try with: $unshift: [{node: addedReview}]. Depending on your addCodeReview mutation.

Resources