Run Apollo query only on React component mount (without queryData and lifecycle) - graphql

I'm using Apollo extensively in a fairly big React app I'm building, and I've found myself facing the same limitation several times.
I want to perform a query only on component mount, so that a change of this component sub-route will no re-trigger the query. I also really want to keep the container pattern, where I declare my query in the container, wrap my component and forget about it, so that my component itself remains clean of any Apollo stuff.
So far, I've been able to do that by making my own Apollo high-order component that takes a component, a query and its options and returns a new component that will automatically run queryData on componentDidMount. Here's the code. I then use it this way: apolloQueryHOC(MyComponent, queryOptions);
But on a new component I've started implementing paging, and this approach simply doesn't work/becomes way too ugly for the complex paging logic I've implemented. The thing is, it works like a charm when I use the basic Apollo container approach. But it runs on every route/prop change.
So my question is, is there a way to run a "container" query only on mount, other than using withApollo and such?

Ah, the problem was actually that I was handling auth in a middleware, so my query had '' as token, and the token was fetched from indexedDB and added to the query in the middleware, overriding ''.
So the query result stored in Apollo store (with the proper token as a param) was never matching the query with '' as token, resulting in Apollo querying again and again from the server.

Related

ApolloClient - run multiple async requests with different input/variables - something like React-Query's useQueries

Apologies if I've just managed to miss it in the docs, but I can't find a way to do this in Apollo Client.
I've read about query batching, but this in fact the opposite of what I want to do. I want my queries sent as separate isolated queries.
Happy to expand on details if needed, but I think the title says it all.
so, my solution has been to create a new component that
returns null (i.e. renders nothing)
runs a useQuery and puts the result into an array (who's setter is passed in from the parent)
This new component sits inside a loop that iterates all my different variable sets that I want to fire the query with.

How do I generate fragment types for apollo client?

I have an app written with reason-react using apollo-client. I have defined some fragments on the frontend to basically reuse some field definitions. I'm setting up automated tests for a components that uses fragments, but I keep getting this warning saying I need to use the IntrospectionFragmentMatcher.
'You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types. Apollo Client will not be able to accurately map fragments. To make this error go away, use the `IntrospectionFragmentMatcher` as described in the docs: https://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher'
I've tried setting up the fragment matcher according to the docs. The codegen result returns no types:
{
"__schema": {
"types": []
}
}
When I queried my server and looked at the manual method recommended by apollo-client, I noticed it would also return no types.
Another strange thing is that when I don't use the fragment matcher, I get the mocked response back but I just get the warnings from apollo. If I do use it then the mocked response doesn't return correctly.
Why would I query the graphql api for fragments defined in my frontend code? Why would I only received these errors when running the tests & using mock data, but not when running my actual application?
As the error states, the default fragment matcher does not work on intersection or union types. You will need to use Apollo's IntrospectionFragmentMatcher. It works by asking the server (introspecting) for information about your schema types, and then providing that information for reference to the cache so that it can match the fields accurately. It's not querying the server for information about the fragments you are defining on the front end, it's asking for data about the GraphQL schema that must be defined on your back end so that it can properly relate the two. There is an example in the documentation, also more information here.
As for why your server is not returning any types, that is a separate issue that would require more info to debug. If you're using Apollo Server, doublecheck your schema to make sure all the necessary types are defined properly and that you are passing them into the server when it's initialized.

How to use a Apollo GraphQL query result as the input of another one? Aka: request chaining

I know this has been asked a couple of times before, but I have found no definitive solution to whether this is possible with GraphQL. And I have a strong feeling this should be possible as it should be relatively easy to implement due to GraphQL queries running sequentially in Apollo.
I have a situation where I'm doing a GraphQL mutation first on the client, and then immediately after doing a query which uses the results from the previous query. This causes a needlessly long response time waiting for the server to respond to both requests. The requests look like this:
mutation createWebSession($authId: ID!) {
webSession: createWebSession(authId: $authId) {
token
userId
}
}
query listUserPaymentMethods($userId: ID!) {
userPaymentMethods: paymentMethods(userId: $userId) {
id
}
}
I know that one simple band-aid solution to avoid making 2 round trips to the server is creating a new single GraphQL mutation endpoint that does both services on the back end. But that seems to defeat the purpose of writing modular, reusable GraphQL endpoints. As such, I'm curious if someone knows if Apollo GraphQL supports a cleaner way to chain 2 requests in which the results from the previous one are available to the next one as inputs.
Any help would be greatly appreciated, thanks.
This is a limitation that specific to GraphQL in general. There is no way to do this in a single request for a couple of reasons:
While a GraphQL document may include any number of operations, only a single operation will be executed. If a document includes multiple operations, all operations must be named and the request must include an operationName parameter that specifies which operation to execute. In other words, while you can combine multiple queries into a single operation, or multiple mutations into a single operation, you cannot cannot mix-and-match queries and mutations.
Given any two fields that share the same "parent" field, both fields will resolve at the same time. The only exception to this are root level mutation fields, which do resolve in sequence. As such, GraphQL does not support any syntax that would let you reference another field and use it as the input to some argument.
One possible workaround is to include a field in your createWebSession payload type whose field is the Query type. I illustrate this approach in this article as a means of refetching queries but it would work for what you're trying to do as well.

How can I use isValidJSValue to validate a query variable in my client code?

I'm writing client-side code for an app that will query a GraphQL server. In a couple of places in my code, I'm passing around data that will eventually get turned into a query variable, so it needs to validate against a specific GraphQLInputType in my schema. On looking into some of the utilities that graphql-js provides, it looks like the isValidJSValue checker is exactly what I'm looking for, and its comments even mention that it's intended to be used to do just that.
The issue is that I don't have access to the GraphQL type I want to validate against as a JS object, which is what I'm pretty sure that function is looking for. I'm importing my schema (as an npm depdendency) as JSON, or I also have it in the schema notation. Is there some other utility I can use to get the JS type I need from one of those sources, and then use that to check my data with isValidJSValue? Or is there some other way I could go about this that I just haven't thought of?
You can use the JSON schema you have imported to construct an actual GraphQL schema instance using buildClientSchema here: https://github.com/graphql/graphql-js/blob/master/src/utilities/buildClientSchema.js
Then, it should be a simple matter of looking in the types field of the resulting schema to find your input type, and then calling isValidJSValue on it.
I'm curious, though - why validate the value on the client before sending it, rather than just relying on the validation the server will do?

Django client side query construction

I'm making a pretty standard AJAXy (well, no XML actually) web page. The browser makes a bunch of API queries that return JSON to run the site. The problem is, I need to add to the API interface each time the page needs to do something new. The new API interface is usually little more than a database query followed by mapping the returned objects to JSON.
What I'd like to do is to get rid of all that server-side duplication and just have the page make database requests itself (using the model interface), but in a way that is safe (i.e. just read only ones). I think this would amount to an interface for constructing Q objects using JSON or something like that, and then send that up to the server, run the query, and return the results. Before I go making my own half-broken architecture for this, I'm wondering if this has already been done well. Also, is this even the best way to go about eliminating this duplication?
Thanks
Search multiple fields of django model without 3rd party app
Django SQL OR via filter() & Q(): Dynamic?
Generate a django queryset based on dict keys
Just replace with operator.and_ where appropriate.

Resources