updateQueries not getting called - apollo-client

Why isn't updateQueries getting called for me? I think I'm doing exactly what the docs say and have compared my code to other similar questions. What am I missing?
Package versions:
apollo-angular#0.13.0
apollo-client#1.0.4
My code:
//same es6 module, above my class definition
const RecentSearchesQuery = gql`
query recentSearch {
recentSearch {
id
query
lastUpdated
userId
}
}
`;
const RecentSearchesMutation = gql`
mutation recentSearchSave($query:String!) {
recentSearchSave(query: $query)
}
`;
...
//my class method
updateRecentSearches(query: string) {
const updateQueries: MutationQueryReducersMap = {
RecentSearch: (prev: Object, {mutationResult}) => {
//execution doesn't get here
debugger;
alert('updateQueries handler in RecentSearchesMutation mutation for recentSearch');
...
}
};
return new Promise((resolve, reject) => {
this.apollo.mutate<any>({
mutation: RecentSearchesMutation,
variables: {query},
updateQueries
})
.subscribe({
next: ({data}) => {
resolve();
},
error: (error: ApolloError) => {
reject(error);
}
});
});

I never did get updateQueries working but the recommended way is now to use update (also a mutation option). Using update worked for me and this article was a very helpful:
https://dev-blog.apollodata.com/apollo-clients-new-imperative-store-api-6cb69318a1e3

Related

How to access data loaded with gatsby-source-graphql in a resolver?

In Gatsby how can I create a resolver that uses data loaded by the gatsby-source-graphql plugin. I'm having trouble figuring out to query the data inside a resolver. Can this be done? Any advice on what I'm missing would be helpful.
something like this in gatsby-node.js ...
exports.createResolvers = ({ createResolvers }) => {
createResolvers({
Query: {
getStructure: {
type: `Structure`,
async resolve(source, args, context, info) {
// assume gatsby-config.js is configured with gatsby-source-graphql and this node exists
const myGraphQlApiNode = await context.nodeModel.runQuery({
query: {
filter: {
fieldName: { eq: "myGqlApi" }
}
},
type: "GraphQLSource"
});
const someGqlApiData = // query all of type MyGqlApi_SomeTypeFromGqlApi loaded via gatsby-source-graphql
return toStructure(someGqlApiData)
}
}
}
});
};
It may be an unofficial solution
Because gatsby doesn’t provide graphql method in createResolvers but do it on createPages
you can do st like this
in gatsby-node.js
let apiHelperGraphql = null
exports.createPages = async ({ actions, graphql }) => {
// steal it from create Pages
apiHelperGraphql = graphql
}
exports.createResolvers = ({ createResolvers }) => {
// and call it here, do what ever you want
apiHelperGraphql(`same as grapql syntax`)
}

orderBy: the results from update cache query

Working on a react apollo graphcool project
I've got my mutation update working, however I would like to filter the results, the results only filter on page refresh?
Looking at cache.writeQuery() the docs say get the query and concat to that so i guess thats why its not filtering. Is there anyway to query after?
Here the code from my CreatePost component
import React from 'react';
import gql from "graphql-tag";
import { Mutation } from "react-apollo";
const GET_POSTS = gql`
{
allPosts(orderBy: createdAt_DESC) {
id
title
content
}
}
`;
const CREATE_POST = gql`
mutation createPost($title: String!, $content: String!){
createPost(title: $title, content: $content){
id
title
content
}
}
`;
const udpateCache = (cache, { data: { createPost } }) => {
const { allPosts } = cache.readQuery({ query: GET_POSTS });
cache.writeQuery({
query: GET_POSTS,
data: { allPosts: allPosts.concat([createPost]) }
})
}
const CreatePost = () => {
//vars for the input refs
let titleInput
let contentInput
return (
<Mutation
mutation={CREATE_POST}
update={udpateCache}
>
{createPost => ( //##form and onSubmit ##// ) }
</Mutation>
)
}
export default CreatePost
When you do your writeQuery you also need to pass in any variables used, to make sure you receive the same information from the cache.
const udpateCache = (cache, { data: { createPost } }) => {
const { allPosts } = cache.readQuery({ query: GET_POSTS });
cache.writeQuery({
query: GET_POSTS,
data: { allPosts: allPosts.concat([createPost]) },
variables: { orderBy: /* input */ }
})
}

gatsbyjs query data from graphcms with status condition throw error object undefiend

Hello i have a gatsbyjs site that i tried to pull data of model 'job' from graphcms. if i pull alljob. the query works fine but if i try to put condition to pull only the job with the status field pubished. it didnt pull any data and throw an error:
TypeError: Cannot read property 'allJob' of undefined
Here's my gatsby-node.js:
const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
resolve(
graphql(request).then(result => {
if (result.errors) {
reject(result.errors)
}
return result;
})
)
});
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators;
const getJobs = makeRequest(graphql, `
{
allJob(where: {status: PUBLISHED}) {
edges{
node{
id
}
}
}
}
`).then(result => { result.data.allJob.edges.forEach(({ node }) => {
createPage({
path: `/job/${node.id}`,
component: path.resolve(`src/templates/jobTemplate.js`),
context: {
id: node.id,
}
})
console.log(node.id)
})
}
)
return getJobs;
};
Gatsby doesn't understand allJob(where: {status: PUBLISHED}) as it's the wrong syntax.
You would want to use filter instead. I can't give you an example as I don't know how the structure is but can advise you to run gatsby develop and go to GraphiQL (http://localhost:8000/___graphql) and use it's autocomplete feature (Ctrl + Space) to get the right filter.
More information: https://www.gatsbyjs.org/docs/graphql-reference/#filter

React Apollo subscription bypasses the graphql wrapper

I have a sample app called GraphQL Bookstore that creates books, publishers and authors and shows relationships between them. I am using subscriptions to show updates in real time.
For some reason my BOOK_ADDED subscription is bypassing the graphql wrapper completely. It is calling the wrapped class with the books prop set to undefined. Relevant parts of the code are shown below (you can see the full code here).
class BooksContainerBase extends React.Component {
componentWillMount() {
const { subscribeToMore } = this.props;
subscribeToMore({
document: BOOK_ADDED,
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) {
return prev;
}
const newBook = subscriptionData.data.bookAdded;
// Don't double add the book
if (!prev.books.find(book => book.id === newBook.id)) {
return Object.assign({}, prev, {
books: [...prev.books, newBook]
});
} else {
return prev;
}
}
});
}
render() {
const { books } = this.props;
return <BooksView books={books} />;
}
}
...
export const BooksContainer = graphql(BOOKS_QUERY, {
props: ({ data: { loading, error, subscribeToMore, books } }) => ({
loading,
error,
subscribeToMore,
books
})
})(LoadingStateViewer(BooksContainerBase));
Basically when a subscription notification is received by the client, the updateQuery() function is called - as expected. However, as soon as that function exits, the render() method of the wrapped class is called directly with books set to undefined. I expected that the graphql wrapper would be called, setting the props correctly before calling the render() method. What am I missing?
Thanks in advance!

Apollo GraphQL: Calling a Query Twice with apolloClient.query?

I have the following query:
const GET_MY_USERINFOFORIMS_QUERY = gql`
query($userID: String!){
myUserDataForIMs(userID:userID){
name_first
name_last
picture_medium
}
} `;
const withUserInfoForIMs = graphql(GET_MY_USERINFOFORIMS_QUERY, {
options({ userID }) {
return {
variables: { userID: `${userID}`}
};
}
,
props({ data: { loading, myUserDataForIMs } }) {
return { loading, myUserDataForIMs };
},
name: 'GET_MY_USERINFOFORIMS_QUERY',
});
From the Apollo docs, it looks like I may be able to call this query twice from inside the component, using apolloClient.query, doing something like this:
client.query({ query: query1 })
client.query({ query: query2 })
Is there a way to call the query twice, passing a different userID each time?
Found it. :)
const localThis = this;
this.props.ApolloClientWithSubscribeEnabled.query({
query: GET_MY_USERINFOFORIMS_QUERY,
variables: {userID: fromID},
}).then((result) => {
localThis.setState({ fromAvatar: result.data.myUserDataForIMs[0].picture_thumbnail });
});
this.props.ApolloClientWithSubscribeEnabled.query({
query: GET_MY_USERINFOFORIMS_QUERY,
variables: {userID: toID},
}).then((result) => {
localThis.setState({ toAvatar: result.data.myUserDataForIMs[0].picture_thumbnail });
});
If there's a better/more efficient way, please post it.
You can do this by passing Apollo's refetch() method into your component's props alongside the data:
const withUserInfoForIMs = graphql(GET_MY_USERINFOFORIMS_QUERY, {
options({ userID }) {
return {
variables: { userID: `${userID}`}
};
},
props({ data: { refetch, loading, myUserDataForIMs } }) {
return { refetch, loading, myUserDataForIMs };
},
name: 'GET_MY_USERINFOFORIMS_QUERY',
});
...then somewhere in your component, you can refetch the data "manually":
theUserWasChangedSomehow(userID) {
this.props.refetch({ userID });
}

Resources