How to run a graphQL query with react-apollo? - reactjs

My GraphQLServer query:
query {
sources {
name
id
}
}
returns array of objects like so:
{
"data": {
"sources": [
{
"name": "bootstrap.css",
"id": 1
},
{
"name": "normalize.css",
"id": 2
}
]
}
}
Trying to understand how to call it from React (redux). I tried:
function mapQueriesToProps( {ownProps, state}) {
return {
data: {
query: gql`
query {
sources {
id
name
}
}
`,
forceFetch: false,
returnPartialData: false,
},
};
};
But nothing happens. Just get loading: true. I'm using apollo-client and got it all wired up according to docs (I think). By that I mean I'm using connect(mapQueriesToProps) etc.
When does the query actually get run?
Does it automatically get run when component loads?
Is there a step I need to do to wait for data to return?
How does the component know to wait for the data?
Is it alright to return an array? I couldn't find any examples of returning an array in the docs.
I only want to run this once, not do any polling or anything. Is that the only way?
This is my first test of Apollo. Any guidance appreciated, because the docs are rather skimpy for beginners.

Have you tried naming the query? I.e. writing query abc { instead of just query {. If that fixes the problem, you should file an issue on react-apollo.
If it doesn't work, you can start narrowing down the error by checking if there are any errors in the console and checking in the network tab if the browser actually makes a request.

Strangely, this 1st method works for me...
Assuming:
import gql from 'graphql-tag';
import { graphql } from 'react-apollo';
You might just be able to (e.g):
const getSources = gql`
query {
sources {
id
name
}
}
`;
export default graphql(getSources) (connect(mapStateToProps, mapDispatchToProps)(YouContainer));
YouContainer props.data will have your query result.
And this 2nd method, also works (probably the best approach):
const getSources = graphql(gql`
_your_query_here_
`);
const connector = connect(mapStateToProps, mapDispatchToProps);
export default connector(getSources(YourContainer));
And as #helfer mentioned, you should name your query also.

Related

Is their a way to just write to the cache without querying in apollo client?

Preface:
With the addition of server-side components in react sometimes it makes sense to fetch some data on the server side, but I would still like to use the apollo client cache it seems like it is a waste to try to fetch data that I already have available (Passed down via props)
Question
Is there a way to just write to the cache without attempting to fetch the data
Code:
'use client'
import { useQuery, gql, } from "#apollo/client";
import { Event as EventType } from '#/gql/index';
interface Props {
events: EventType[];
}
const GET_EVENTS = gql`
query Events {
events {
_id
createdBy
name
date
description
}
}
`;
const WriteEventsCache: React.FC<Props> = ({ events }) => {
// Do I have to do this?
const { data } = useQuery(GET_EVENTS, {
});
// Or can i just do something like this
client.writeQuery({
query: gql`
query Events {
events {
_id
createdBy
name
date
description
}
}
`;
data: { // Contains the data to write
},
return (
<div>
</div>
)
}
export default WriteEventsCache;
You can write directly to the cache with cache.modify
You can also query the cache without hitting the server by using a cache-only fetchPolicy.

react apollo cache.write issue

I use "#apollo/client": "^3.5.9"
and have an issue when try to update cache
Here is the problem:
I use useMutation hook and inside this hook try to update my cache
const [createUser, { data, loading, error }] = useMutation(addUser, {
update(cache, { data }) {
const newUser = data?.createUser?.user;
const existUsers: any = cache.readQuery({
query: allUsersQuery
});
cache.writeQuery({
query: allUsersQuery,
data: {
allUsers: [...existUsers?.allUsers.edges, newUser]
}
});
}
});
I receive an errors below
Error 1:
react_devtools_backend.js:4061 Missing field 'edges' while writing result {
"__typename": "UserSchema",
"id": "acb4e46f-b80a-42ee-b2d5-c838b63b2c63",
"name": "456"
}
Error 2:
react_devtools_backend.js:4061 Cache data may be lost when replacing the allUsers field of a Query object.
To address this problem (which is not a bug in Apollo Client), define a custom merge function for the Query.allUsers field, so InMemoryCache can safely merge these objects:
existing: {"__typename":"UserConnection","edges":[{"__typename":"UserEdge","node":{"__ref":"CustomUserNode:6a845e81-ae09-46c5-9b5c-5e250efbad71"}},{"__typename":"UserEdge","node":{"__ref":"CustomUserNode:2cff31b1-ed2b-4245-b7d9-268df82b8c4f"}},{"__typename":"UserEdge","node":{"__ref":"CustomUserNode:95869b70-4c7b-42f1-baad-d7c358caa4ff"}},{"__typename":"UserEdge","node":
I try to googled, try to wrap in try and catch blow, but it doesn't work.
I supposed i missing something but i do not what exactly.
Any comments highly appreciated.

Refetching a query using Apollo-Client throws an error

I am using Apollo-client to post a mutation to my graphql server. When the mutation is completed, I want to refetch that data. I tried using the refetchQueries argument in the useMutation hook, however I receive this error when I execute the code:
query option is required. You must specify your GraphQL document in
the query option.
This is the line of code that sends the mutation:
const [addUser, { data, loading, error }] =
useMutation(ADD_USER_QUERY, {
refetchQueries:[GET_USERS_QUERY]
});
This is my query (the hardcoded arguments were to see if the issues was due to passing variables):
export const ADD_USER_QUERY = gql`
mutation {
createUser(name: "Albert Einstein", email: "albert#yahoo.ca") {
id
name
}
}
`;
Thank you!
Alright so I figured out what the issue was. I had to pass an object with a "query" key in the refetchQueries array:
const [addUser, { data, loading, error }] =
useMutation(ADD_USER_QUERY, {
refetchQueries: [{ query: GET_USERS_QUERY }],
});
It's weird though because it isn't mentioned in the ApolloDocs. They simply use an array...
// Refetches two queries after mutation completes
const [addTodo, { data, loading, error }] = useMutation(ADD_TODO, {
refetchQueries: [
GET_POST, // DocumentNode object parsed with gql
'GetComments' // Query name
],
});
Does anyone know why that is?
Thanks!

`useLazyQuery` From Apollo Seems To Trigger Infinite Render Loop

I try to write a Shopify component using Next.js and the Apollo Client. This is my cart component, which always enters an infinite loop (hundreds of renders per second):
import { gql, useLazyQuery } from "#apollo/client"
export default function Cart() {
const checkoutCreateMutation = gql`
mutation checkoutCreate($input: CheckoutCreateInput!) {
checkoutCreate(input: $input) {
checkout {
id
}
}
}
`
const cartLineItemsQuery = gql`
query ($id: ID!) {
node(id: $id) {
id
}
}
`
const cartId = "MY_CART_ID"
const [getCartItems, data] = useLazyQuery(cartLineItemsQuery)
getCartItems({ variables: { id: cartId } })
return (
<p>This is your data: {JSON.stringify(data)}</p>
)
}
I suspect that my queries may be wrongly formatted, but I'd still like to have an error thrown in this case instead of the infinite loop. Or could the problem also be located outside of that component? When I delete the getCartItems(...) line, no infinite loop occurs.
The reason I use useLazyQuery instead of useQuery is that this code is already reduced, originally I first look if a cart ID exists in the cache and if this is not the case I request a new cart ID, otherwise I query the content of the cart.
I misunderstood the idea behing useLazyQuery. It functions more similar to useMutation, where the execution triggers a rerendering. In my case, the working solution was to use useQuery with a skip parameter, so the query will only execute if, e.g., the cart ID variable is defined.

React Apollo GraphQL : Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a "gql" tag?

I keep getting this error when trying to update cache after mutation:
Possible Unhandled Promise Rejection (id: 0):
Invariant Violation: Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a "gql" tag?
The mutation succeeds, then I run this code inside the onCompleted method.
const cards = this.props.client.readQuery({ FETCH_CARDS, variables: { userId: data.createPaymentMethod.userId } });
const { id,
brand,
lastFour,
userId,
stripeID } = data.createPaymentMethod
const paymentMethod = {
id: id,
brand: brand,
lastFour: lastFour,
userId: userId,
stripeID: stripeID,
__typename: 'PaymentMethod',
};
// Write back to the to-do list and include the new item
this.props.client.writeQuery({
FETCH_CARDS,
data: {
paymentMethod: [...cards.paymentMethod, paymentMethod],
},
});
I don't understand what I'm doing wrong. I'm following this guide: https://www.apollographql.com/docs/react/caching/cache-interaction/#writequery-and-writefragment
EDIT: FETCH_CARDS
const FETCH_CARDS = gql`
query PaymentMethod($userId: ID){
paymentMethod(userId: $userId) {
id
brand
lastFour
userId
stripeID
}
}
`;
When this happens to me, the issue is usually as simple as the import for FETCH_CARDS not resolving correctly. It is hard to determine without having the complete example, I'd need to be able to see the entire file for each of the code samples and the directory structure.
For me, the solution was changing readQuery({ FETCH_CARDS to readQuery({ query: FETCH_CARDS and the same for writeQuery(). I agree that their example appears misleading, because they name their gql call "query" instead of a normal all-caps name. But really it's to tee up shorthand object prop notation for readQuery({ query: query.
Ahaa ran into same issue today when I was following similar tutorial from Udemy.
If you were using some other client provider like "graphql-request" or normal fetch calls and then tried switching to "#apollo/client" then I think I have answer for you (and that is also super simple one).
Please pay close attention to packages imported here from different libraries.
import { request, gql } from "graphql-request";
import { ApolloClient, InMemoryCache } from "#apollo/client";
const FETCH_CARDS = gql`
query PaymentMethod($userId: ID){
paymentMethod(userId: $userId) {
id
brand
lastFour
userId
stripeID
}
}`;
Now even after using client.query({FETCH_CARDS }) in correct way where FETCH_CARDS has gql tag I got error as below.
You must wrap the query string in a "gql" tag
So this happens as #apollo/client expects gql tag which is imported from "#apollo/client" only and not from other packages.
Hence, simply after changing the gql import from correct library as below, in this case "#apollo/client" it started working without any issues.
import { gql, ApolloClient, InMemoryCache } from "#apollo/client";
Kindly try this and upvote if you find it useful!
For me the issue was easy to miss, i had import { products } from '~/components/apollo/queries/products';
It needed to be import products from '~/components/apollo/queries/products';
Basically remove the { } around the queried attribute products

Resources