Graphql sending empty string - graphql

I am using graphql to get some data.
let { loading, error, data } = useQuery(GET_JOBS_SEARCH, {
variables: {
category: category,
type: jobType
}
});
Now when I update the category the API gets called with variables like
variables: {category: "leadership", type: ""}
Now I don't want the type:'' in my call.

Related

Graphql apollo-client useMutation variable with gql , GraphQLInputObjectType does not check for input object fields

could anyone please help me understand on how to validate the input argument object type on apollo client , i am trying to make sure that passing additional fields on the input object fails the query . But it works even if i pass additional fields (Note : I want the validation on front end and not on the server)
const mutationInput = new GraphQLObjectType({
name: 'mutationInput',
fields: {
Id: String,
statusCode: String,
}
});
const GET_DATA = gql`
mutation($in: ${mutationInput}!){
getData(in: $in) {
status
}
}
}`;
//usage
const [getData, { error,loading }] = useMutation(
GET_DATA,
{
...
}
)
getData({
variables: {
in: {
statusCode:"OK",
ID:"azz12",
extraField:"some value" //Validation needs to fail as this field is not defined on input object, but never fails on front end
}
}

Apollo-client: Add item to array in cache

Suppose I have the following GraphQL types:
type User {
id: String!
posts: [Post!]!
}
type Post {
id: String!
text: String,
}
And here is a mutation that returns the updated post:
mutation addNewPost(
$userId: String!
$text: String!
) {
addNewPost(userId: $userId, text: $text) {
id
text
}
}
After running this mutation my cache contains a new entry of a post. How do I add it to the user's posts array? I have tried cache.writeQuery and cache.modify but I cannot figure it out.
We do push the item into array inside the update function, which is one of the options of useMutation.
I'm writing the whole mutation so that you can get the idea 💡, let have a look at example:
By Update function:
const [createPost, { data, loading, error }] = useMutation(CREATE_POST, {
update(cache, response) {
// Here we write the update
// Step 1: Read/Fetch the data 👈
const data = client.readQuery({
query: FETCH_POSTS_QUERY,
});
// Step 2: Update the cache by immutable way 👈
client.writeQuery({
query: FETCH_POSTS_QUERY,
data: {
getPosts: [response.data.createPost, ...data.getPosts],
},
});
},
variables: formValues,
});
By refetchQueries:
That's really shortcut 🔥 way to update the cache, by using DocumentNode object parsed with the gql function
const [createPost, { data, loading, error }] = useMutation(CREATE_POST, {
refetchQueries: [ 👈
FETCH_POSTS_QUERY
'fetchPosts`' // OR Query name
],
variables: formValues,
});
You're going to want to directly write to the Apollo cache in order to update the other entities that your mutation has modified.
Have a look at the docs https://www.apollographql.com/docs/react/data/mutations/#making-all-other-cache-updates here for specifics (you're going to want to use cache.modify and cache.writeFragment)

Post data to a graphql server with request-promise

I'm using the request-promise library to make http request to a graphql server. To achieve a query, I'm doing this:
const query = `
{
user(id:"123173361311") {
_id
name
email
}
}
`
const options = {
uri: "http://localhost:5000/graphql",
qs: { query },
json: true
}
return await request(options)
The above code is working fine. However I'm confused about how to go about a mutation since I need to specify both the actual mutation and the inputData like this:
// Input
{
name: "lomse"
email: "lomse#lomse.com"
}
const mutation = `
mutation addUser($input: AddUserInput!){
addUser(input: $input) {
_id
name
email
}
}
`
const option = {
uri: "http://localhost:5000/graphql",
formData: {mutation},
json: true,
// how to pass the actual data input
}
request.post(option)
Or is it that the request-promise library isn't designed for this use case?
Use body, not formData. Your body should consist of three properties:
query: The GraphQL document you're sending. Even if the operation is a mutation, the property is still named query.
variables: A map of your variable values serialized as a JSON object. Only required if your operation utilized variables.
operationName: Specifies which operation to execute. Only required if your document included multiple operations.
request.post({
uri : '...',
json: true,
body: {
query: 'mutation { ... }',
variables: {
input: {
name: '...',
email: '...',
},
},
},
})
The graphql-request library seems to do what I needed the request-promise library to do.
import { request } from 'graphql-request'
const variables = {
name: "lomse",
email: "lomse#lomse.com"
}
const mutation = `
mutation addUser($input: AddUserInput!){
addUser(input: $input) {
_id
name
email
}
}
`
response = await request(uri, mutation, {input: variables})

Error writing result to store for query. Cannot read property 'query' of undefined

I'm getting an error when writing a query to store after a mutation. The mutation works and i'm able to read the query post mutation. When i write the same query to the store cache i get the following Error:
index.js:2178 Error: Error writing result to store for query:
query ($applicationId: Int) {
vApplicationApprovalChainList(ApplicationId: $applicationId) {
id
approvalOrder
approverId
name
applicationId
__typename
}
}
Cannot read property 'vApplicationApprovalChainList' of undefined
at writeToStore.js:101
at Array.forEach (<anonymous>)
at writeSelectionSetToStore (writeToStore.js:97)
at writeResultToStore (writeToStore.js:75)
at InMemoryCache../node_modules/apollo-cache-inmemory/lib/inMemoryCache.js.InMemoryCache.write (inMemoryCache.js:99)
Here is my code.. the mutation and store.readQuery works but the store.writeQuery gives above error. Thank you in advance for any feedback.
APPROVERSLIST_QUERY = gql`
query ($applicationId:Int){
vApplicationApprovalChainList(ApplicationId:$applicationId){
id
approvalOrder
approverId
name
applicationId
}
}
`;
handleClick() {
const { row, mutate} = this.props;
mutate({
variables: {
id: row.id
},
update: (store, { data: { deleteApprover } }) => {
const newdata = store.readQuery({
query: APPROVERSLIST_QUERY,
variables: { applicationId: row.applicationId }
});
console.log(newdata);
newdata.vApplicationApprovalChainList = newdata.vApplicationApprovalChainList.filter(approver => approver.id !== deleteApprover.id);
store.writeQuery({
query: APPROVERSLIST_QUERY, newdata });
}
});
}
You're not passing in the new data to writeQuery. The object passed to writeQuery must have a property named data containing the new data. Additionally, since your query contains variables, you will need to include that information as well.
store.writeQuery({
query: APPROVERSLIST_QUERY,
data: newdata,
variables: {
applicationId: row.applicationId,
},
});
Please see the official docs for more examples and a more thorough explanation of the two methods.

graphql: sort by nested field

Let's say I have 2 tables:
- Users (id, name, post)
- Posts (id, message, user)
How can I fetch first 10 Posts order by User's name(desc)?
Here's how my schema looks like:
var PostType = new GraphQLObjectType({
name: "Post",
fields: () => ({
id: { type: GraphQLInt },
message: { type: GraphQLString },
user: {
type: UserType,
args: {
orderBy: { type: sortType }
},
resolve(parent, args) {
console.info("Post resolve called.");
return userMap[parent.user];
}
}
})
});
var RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
allPosts: {
type: new GraphQLList(PostType),
resolve(parentValue, args) {
console.info("allPosts resolve called.");
return postData;
}
}
}
});
And Query:
{
allPosts {
message
user (orderBy: {field: "name", direction: ASC}) {
name
}
}
}
Is there any way, I can call user resolver function before allPosts resolver function? Because, I am trying to fetch 10 users sorted by name and then pass post ids to allPosts resolver.
GraphQL fields are resolved in a top-down fashion. That means allPosts is resolved first, then then message and user fields (simultaneously) and then the name field. This has to happen, as the "parent" or root field's resolved value determine's the value that's then passed to the resolver for its children fields as the root value. Information flows from "higher" resolvers to "lower" ones, but not the other way around.
Your orderBy argument here probably should be an argument on the allPosts field rather than the user field. There's two reasons to do that: (1) conceptually, regardless of the sort criteria, you are sorting the Posts returned by allPosts -- by convention, it just makes sense to put the sort there; (2) the argument is probably needed by the allPosts resolver more than it's needed by the user resolver.
To make the above work, you'll probably need to modify how you identify the sort criteria (making field a path like user.name for example). You may also need "lift" the logic for populating the users up into the allPosts resolver. For example:
resolve(parentValue, { sortBy: { path, direction } }) {
const data = postData.map(post => {
post.user = userMap[post.user]
return post
});
// using lodash
return orderBy(data, [(post) => get(post, path)], [direction])
}
It is possible to determine the selection set for other fields inside the request, including the arguments, by parsing the info object that's passed in as the fourth parameter to the resolver function. It's a pain though and I don't know if this particular case really justifies doing all that. You can read more about that approach in this answer.

Resources