Relay generating invalid query after using `setVariables`-- am I doing something wrong? - reactjs

For some reason, if I generate a root query which takes in parameters before injecting the child component, like so:
import Relay from 'react-relay';
export default {
production: (Component) => Relay.QL`
query {
getProduction(id: $productionId) {
${Component.getFragment('production')}
}
}
`
};
Relay originally generates this query:
query MyProductionDetailsQuery($id_0:ID!,$where_1:ProductionRoleWhereArgs!) {
getProduction(id:$id_0) {
id,
...F0
}
}
fragment F0 on Production {
id,
...
_roles4oPiwv:roles(first:10,where:$where_1) {
edges {
node {
id,
...
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
}
}
variables:
{id_0: "UHJvZHVjdGlvbjoxNg==", where_1: {archived: {eq: true}}}
However, If the Component's relay container has variables of its own, running this.props.relay.setVariables({...variables}) completely changes the request query generated by relay into something like this:
query My_production_details_page_ProductionRelayQL($id_0:ID!,$where_1:ProductionRoleWhereArgs!) {
node(id:$id_0) {
...F0
}
}
fragment F0 on Production {
id,
_roles6J5gK:roles(first:10,where:$where_1) {
edges {
node {
id,
...
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
}
}
variables:
{id_0: "UHJvZHVjdGlvbjoxNg==", where_1: {archived: {eq: false}}}
However, setVariables works fine if I have a root query with no parameters:
import Relay from 'react-relay';
export default {
viewer: (Component, variables) => Relay.QL`
query {
viewer {
${Component.getFragment('viewer', { ...variables })}
}
}
`
};
Here's the generated query:
query ViewerQuery($where_0:ProductionWhereArgs!) {
viewer {
...F0
}
}
fragment F0 on Viewer {
user {
_productions2IPZAw:productions(first:10,where:$where_0) {
edges {
node {
id,
...
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
},
id
}
}
variables:
{where_0: {expDate: {gt: "2016-11-04T16:29:11.677Z"}, archived: {eq: false}}}
After setVariables in the working setup:
query ViewerQuery($where_0:ProductionWhereArgs!) {
viewer {
...F0
}
}
fragment F0 on Viewer {
user {
_productions1CyNvL:productions(first:10,where:$where_0) {
edges {
node {
id,
...
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
},
id
}
}
variables:
{where_0: {expDate: {lt: "2016-11-04T16:34:12.537Z"}, archived: {eq: false}}}
versions:
"react-relay": "^0.9.3",
"react-router-relay": "^0.13.5"
I'm not sure if I'm doing something wrong with the configuration, or if it's just a bug on Relay's end.
Does anyone know what might be causing this issue?

When you run setVariables it leads to refetching only necessary data.
Relay looks which part of query could be affected by changing variable and requests from GraphQL server needed fragment.
It is possible because of Node interface(i.e. fetching object by opaque Relay id). See more in documentation.
I think, in your case you should implement Node Interface for Production type on GraphQL server.

Related

Relay-style pagination with Apollo Client

I am trying to paginate 2 relay-style fields posts_connection and comments_connection
For instance, the query is extremely simple,
const QUERY = gql `
PostsQuery($comments_first: Int, commments_after: String) {
posts_connection {
edges {
node {
...INFO_ABOUT_A_POST
comments_connection(first:$comments_first, after:$commments_after) {
edges {
node {
...INFO_ABOUT_A_COMMENT
}
}
}
}
}
}
}
`
To do this with Apollo client, we configure the cache using relayStylePagination(), as in https://www.apollographql.com/docs/react/pagination/cursor-based/#relay-style-cursor-pagination
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
posts_connection: relayStylePagination(),
},
},
posts: { // posts is the type of a single post node
fields: {
keyFields: ["postid"],
comments_connection: relayStylePagination()
}
},
comments: {
keyFields: ["commentid"],
},
}
}
My process is
Run the initial query,
data has a single initial comment, COMMENT1
fetchMore comments
fetchMore({variables : {comments_after:PREVIOUS_END_CURSOR} })
We fetch a new comment COMMENT2
The issue: data should contain [ COMMENT1, COMMENT2]
Instead, the new comment overwrites the old one, and data only contains COMMENT2
Why is this happening and how do I solve it?

How to get Apollo gql codgen to work with frontend nextJS

I am using nextJS, I want my front end react queries with apollo to be typed out, but no configuration is working. I get an unknown error on my query when I use import {gql} from src/__generated__/gql and the following message when I hover over gql():
The query argument is unknown! Please regenerate the types
My question is do I need to do something different because I am using nextJS? I want to be able to use TypeScript with Apollo Client code gendocs so my gql queries will be typed
My entire pothos schema is in my pages/api/index.ts file (I do not yet know how to spread this code out into multiple files)
Example Query:
const CREATED_EVENT_QUERY = gql(`
query EventById($id: mongoId!) {
eventById(id: $id) {
_id
name
description
location{
coordinates
}
date
eventApplicants{
name
userId
weight
}
link
weights{
weight
spotsAvailable{
name
userId
}
}
}
}
`);
// Apollo Query
const { loading, error, data } = useQuery(CREATED_EVENT_QUERY, {
variables: {
id: params.id
}
});
I have tried the following configurations:
Apollos recommendation
Link Above
import { CodegenConfig } from '#graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'http://localhost:3000/api',
documents: ['*.ts'],
generates: {
'./src/__generated__/': {
preset: 'client',
plugins: [],
presetConfig: {
gqlTagName: 'gql',
}
}
},
ignoreNoDocuments: true,
};
export default config;
the guilds nextJS recomendation
import type { CodegenConfig } from '#graphql-codegen/cli'
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
config: {
reactApolloVersion: 3
}
}
}
}
export default config
combination of the two
import { CodegenConfig } from '#graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'http://localhost:3000/api',
documents: ['*.ts'],
generates: {
'pages/api/index.ts': {
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
config: {
reactApolloVersion: 3
}
}
},
ignoreNoDocuments: true,
};
export default config;

Apollo client - add new item to list following mutation

I am working on a react app using "#apollo/client": "3.6.5". In the app a user can create payment requests that are displayed in a list.
I need to add a newly created payment request to the list of payment requests in the Apollo cache following the mutation to create one. The problem is the new payment request is not added to the cached list and Apollo does not output any error messages to explain why.
This is my version of the update function I've copied from the Apollo docs to try and update the cache.
const [onCreatePaymentRequest, createPaymentRequest] = useMutation<
CreatePaymentRequest,
CreatePaymentRequestVariables
>(CreatePaymentRequestMutation, {
update(cache, { data: { createPaymentRequest } }) {
cache.modify({
fields: {
paymentRequests(existingPaymentRequests = []) {
const newPaymentRequestRef = cache.writeFragment({
data: createPaymentRequest,
fragment: gql`
fragment NewPaymentRequest on PaymentRequest {
id
amount
status
}
`
});
return [...existingPaymentRequests, newPaymentRequestRef];
}
}
});
}
});
The mutation to create a new payment request:
export const CreatePaymentRequestMutation = gql`
mutation CreatePaymentRequest($input: CreatePaymentRequestInput!) {
createPaymentRequest(input: $input) {
paymentRequest {
id
amount
status
}
}
}
`;
This is query used to fetch payment requests:
export const GetAccountPaymentRequestsQuery = gql`
query GetAccountPaymentRequests(
$accountId: UUID!
$first: Int
$before: String
$last: Int
$after: String
) {
currentUser {
id
accountMembers(filter: { account: { id: $accountId } }) {
edges {
node {
account {
paymentRequests(
first: $first
last: $last
before: $before
after: $after
) {
edges {
node {
id
amount
status
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
}
}
}
}
`;
I think the problem may be that payment requests are nested within the schema. Using the useQuery hook I access the payment requests within a component using the following:
const paymentRequests = data.currentUser.accountMembers.edges[0].node.account.paymentRequests
.edges
I have tried numerous iterations of the update function to get this to work but so far no luck.
Thanks

React Apollo Client - query results mixing up in cache

I use apollo client to fetch book graphs and use relay style pagination. Both of the following NEW_BOOKS query and ALL_BOOKS query works fine independently.
Currently, I am using NEW_BOOKS in the home page and ALL_BOOKS in a popup in the home page.
When the Homepage is opened NEW_BOOKS gets loaded fine.
When the popup is opened and ALL_BOOKS is fetched, newBooks become undefined or the result of ALL_BOOKS query.
Why is this happening?
const { loading, data: newBooks, fetchMore, networkStatus } = useQuery(NEW_BOOKS, {
variables: {
first: PAGE_SIZE,
after: endCursor
},
notifyOnNetworkStatusChange: true
});
const NEW_BOOKS = gql`query GetNewBooks($first:Int!, $after:String){
books(
first: $first, after: $after,
filters: [
{
path: "isNew",
value: true
}
]
) {
totalCount
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
node {
id
name
author {
id
name
}
}
}
}
}`;
-All books query filterable by name
const { loading, data: filteredBooks, fetchMore, networkStatus } = useQuery(ALL_BOOKS, {
variables: {
first: PAGE_SIZE,
after: endCursor,
name: nameFilter
},
notifyOnNetworkStatusChange: true
});
const ALL_BOOKS = gql`query GetAllBooks($first:Int!, $after:String, $name:String){
books(
first: $first, after: $after,
filters: [
{
path: "name",
value: $name,
type: "contains"
}
]
) {
totalCount
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
node {
id
name
copiesSold
author {
id
name
}
}
}
}
}`;
The cache being used looks like this,
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
books: relayStylePagination(),
},
}
},
});
We have to pass keyArgs explictly when relayStylePagination or similar pagination is used.
A keyArgs: ["type"] field policy configuration means type is the only argument the cache should consider (in addition to the field name and the identity of the enclosing object) when accessing values for this field. A keyArgs: false configuration disables the whole system of differentiating field values by arguments, so the field's value will be identified only by the field's name (within some StoreObject), without any serialized arguments appended to it.
KeyArgs documentation here.
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
books: relayStylePagination(["name"]),
},
}
},
});

Populating Github GraphQL in React (Gatsby)

I am trying to create a page displaying my pinned repos. I am using gatsby and have installed the gatsby-source-github-api
{
resolve: 'gatsby-source-github-api',
options: {
token: 'xxxxxxxxx',
},
},
And I have the query populating the data I want in the GraphQL plaryground.
query {
user(login: "mrpbennett") {
pinnedItems(first: 6, types: [REPOSITORY]) {
edges {
node {
... on Repository {
name
description
url
primaryLanguage {
name
color
}
}
}
}
}
}
}
However I am struggling to get that data to populate into a new component I keep getting 7:13 error Cannot query field "user" on type "Query" graphql/template-strings
This is the component
I am not really to sure how to populate the data i need.
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
const PinnedRepos = () => {
const data = useStaticQuery(graphql`
query {
user(login: "mrpbennett") {
pinnedItems(first: 6, types: [REPOSITORY]) {
edges {
node {
... on Repository {
name
description
url
primaryLanguage {
name
color
}
}
}
}
}
}
}
`)
return (
<div>
<p>{data.node.repository.name}</p>
</div>
)
}
export default PinnedRepos
any advice would be greatly appreciated​.
The syntax of your query is the problem here, you need to write the query like
const data = useStaticQuery(graphql`
query user(login: "mrpbennett") {
pinnedItems(first: 6, types: [REPOSITORY]) {
edges {
node {
... on Repository {
name
description
url
primaryLanguage {
name
color
}
}
}
}
}
}
`)

Resources