<Query syntax failing - react-apollo

All right. Need some fresh eyes to spot my error:
Trying to grab content for a JS Carousel from a mongo db via GraphQL (as produced by strapi).
Working in a component with relevant imports:
import { Query } from 'react-apollo'
import { gql } from 'graphql-tag'
import React, { Component } from 'react'
import { Carousel, CarouselItem, CarouselControl, CarouselIndicators, CarouselCaption } from 'reactstrap'
within my class
...snippet...
render() {
const GET_CAROUSELS = gql`
query carousels {
carousels {
_id
caption_header
caption_text
alt_text
slide_file { url }
}
}`
return (
<Query query={GET_CAROUSELS} errorPolicy="all">
{({ loading, error, data }) => {
let cars = data.carousels
if (error) console.log(error)
if (!cars || cars.length == 0){
return <div>No Carousels found</div>
} else {
return (
<React.Fragment>
<Carousel activeIndex={this.activeIndex}
next={this.next}
previous={this.previous} >
{cars.map(carousel => (
<CarouselItem key={carousel._id}>
<img scr={carousel.slide_file.url} />
</CarouselItem>
))}
</Carousel>
I've tried many permutations, and this current code errors with cannot read property of 'map' undefined
My QLGraph playground shows that this query works fine:
query {carousels {
_id
caption_header
caption_text
alt_text
slide_file { url }
}
}
I've tried altering the <Query query, to no avail. Tried with and without letting let cars = data.carousels sometimes just let cars=carousels, etc.
Help, my eyes hurt.

Related

Gatsby and GraphQL: query pdf file using <StaticQuery/>

I am very new to graphQL.
Inside src I have a data folder which contains a pdf named my_cv.pdf
Problem: I am unable to either load it in the browser or able to download it. I get an error There's not a page yet at /data.file.publicURL
gatsby.config.js
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/src/data/`,
name: "data",
},
},
my hero component
this is inside the render() of the class component.
<Resume href="data.file.publicURL" target="_blank">
Download Resume
</Resume>
this is how I am querying it.
<StaticQuery
query={graphql`
query {
pdf: file(name: { eq: "my_cv.pdf" }) {
name
extension
publicURL
}
</StaticQuery>
The problem is that you are aliasing file as pdf, hence the nesting should be:
<Resume href="data.pdf.publicURL" target="_blank">
Download Resume
</Resume>
If you use StaticQuery I think you may want to use something like:
import React from "react";
import { StaticQuery, graphql } from "gatsby";
export default function Header() {
return (
<StaticQuery
query={graphql`
query {
pdf: file(name: { eq: "my_cv.pdf" }) {
name
extension
publicURL
}
}
`}
render={(data) => (
<Resume href="data.pdf.publicURL" target="_blank">
Download Resume
</Resume>
)}
/>
);
}
If you use useStaticQuery hook you can detach the logic from Resume of the StaticQuery component
import React from "react";
import { useStaticQuery, graphql } from "gatsby";
export default function Header() {
const data = useStaticQuery(graphql`
query {
pdf: file(name: { eq: "my_cv.pdf" }) {
name
extension
publicURL
}
}
`);
return (
<Resume href="data.pdf.publicURL" target="_blank">
Download Resume
</Resume>
);
}
In both cases, be sure that the GraphQL query is returning valid data.

Check queried subfields in runtime graphql Nestjs?

I try to optimize one of my queries which returns #ObjectType() like this:
isFeatureEnabled() {
.
.
.
return {
isDistributedInboundEnabled: await getIsDistributedInboundEnabled(),
isBusinessHoursEnabled: await getIsBusinessHoursEnabled(),
};
}
However, when executing this query with :
query GetCompany {
getCompany{
isFeatureEnabled{
isBusinessHoursEnabled
# isDistributedInboundEnabled <--- Do not query this !
}
}
}
both of the functions are executed (await getIsDistributedInboundEnabled(), await getIsBusinessHoursEnabled()).
Can I check which subfields are queried in runtime? That way only required functions will be executed on BE.
Ok, personally used approach described in this link and found it working with nest 8.x.x:
Fortunately, we can access the details about the GraphQL query with the #Info() decorator. The most straightforward way to use it is with the graphql-parse-resolve-info library.
import { Info, Query, Resolver } from '#nestjs/graphql';
import { Post } from './models/post.model';
import PostsService from './posts.service';
import { parseResolveInfo, ResolveTree, simplifyParsedResolveInfoFragmentWithType } from 'graphql-parse-resolve-info';
import { GraphQLResolveInfo } from 'graphql';
#Resolver(() => Post)
export class PostsResolver {
constructor(
private postsService: PostsService
) {}
#Query(() => [Post])
async posts(
#Info() info: GraphQLResolveInfo
) {
const parsedInfo = parseResolveInfo(info) as ResolveTree;
const simplifiedInfo = simplifyParsedResolveInfoFragmentWithType(
parsedInfo,
info.returnType
);
const posts = 'author' in simplifiedInfo.fields
? await this.postsService.getPostsWithAuthors()
: await this.postsService.getPosts();
return posts.items;
}
}

graphql-codegen + typescript-svelte-apollo - Refetch not working?

(Edited)
Refetching with the generated query type seems to work different from the refetch function in Apollo Client useQuery. I don't understand how to phrase it - can anyone provide an example?
I'm realizing the problem is probably either my refetch is not properly phrased, or maybe the store is only hitting the cached query. I've been going over my code for days and I can't figure out what it could be. I've tried await blocks too.
The refetch worked with svelte-apollo, but i'm trying to eliminate that dependency. I've also tried Apollo Client's useQuery, but the whole point of graphql-codegen with typescript-svelte-apollo is to use the generated typescript wrapper for the query.
When I assign the generated query to a reactive constant in my Svelte front-end code,
$: observations = getObservations({ variables: { filter } });
the query does not refetch when i update the query variables, as I would expect.
This is how my svelte template is using the query. The filter object changes based on a form user input. I've tried this with an await block too.
<script lang="ts">
import { getObservations } from '$lib/generated';
$: observations = getObservations({ variables: { filter } });
function handleFilter(event) {
filter = event.detail;
}
</script>
{#if $observations.loading}
Loading...
{:else if $observations.error}
{$observations.error}
{:else if $observations.data}
{#each $observations.data['observations']['edges'] as edge}
<Item node={edge['node']} />
{/each}
{/if}
Since this plugin allows to use the query directly, without Apollo's useQuery, i'm not sure how to phrase a refetch.
If i do $observations.refetch(); inside handleFilter(e), i get an error
Property 'refetch' does not exist on type 'Readable<ApolloQueryResult<GetObservationsQuery> & { query: ObservableQuery<GetObservationsQuery, Exact<{ filter?: FilterObservationsInput; }>>; }>'.ts(2339)
There's nothing fancy in my config. Am I doing something wrong here?
schema: src/graphql/schema.graphql
documents:
- src/graphql/queries.graphql
- src/graphql/mutations.graphql
generates:
src/lib/generated.ts:
plugins:
- typescript
- typescript-operations
- graphql-codegen-svelte-apollo
config:
clientPath: src/lib/shared/client
# asyncQuery: true
scalars:
ISO8601Date: Date
ISO8601DateTime: Date
Here's the client:
export default new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
observations: relayStylePagination(),
},
},
},
})
});
The generated query:
export const getObservations = (
options: Omit<
WatchQueryOptions<GetObservationsQueryVariables>,
"query"
>
): Readable<
ApolloQueryResult<GetObservationsQuery> & {
query: ObservableQuery<
GetObservationsQuery,
GetObservationsQueryVariables
>;
}
> => {
const q = client.watchQuery({
query: GetObservationsDoc,
...options,
});
var result = readable<
ApolloQueryResult<GetObservationsQuery> & {
query: ObservableQuery<
GetObservationsQuery,
GetObservationsQueryVariables
>;
}
>(
{ data: {} as any, loading: true, error: undefined, networkStatus: 1, query: q },
(set) => {
q.subscribe((v: any) => {
set({ ...v, query: q });
});
}
);
return result;
}
Here's the query document that it's built from:
query getObservations($filter: FilterObservationsInput) {
observations(filter: $filter) {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
createdAt
updatedAt
when
where
imgSrcThumb
imgSrcSm
imgSrcMed
thumbImage {
width
height
}
name {
formatName
author
}
user {
name
login
}
rssLog {
detail
}
}
}
}
}

Get state from select form in child component with Gatsby

I code a Gatsby app with a Main page and two components. The value from a select form will be used to query a Postgresql database through a graphql query.
What I can already do: in the form component, I get the value from the select menu and pass it from this child component to the parent (the main page). In the data component, I can query the database with graphql and get the results with hardcoded values.
What I can't do yet: get the value from the select component to the data component and use it in my graphql query.
I tried different ways to get the value without success using this.props.value1 or this.state.value1. I also tested a simple component to make sure I could get the value from the parent to a child component and it worked seamlessly. So it's the way I try to import the value in a querying component that is the problem.
**//Data component**
let val = 88 //for hardcoded test. That works.
const DataPage = () => {
const data = useStaticQuery(query)
return (
<div>
<p>From Postgres: {data.postgres.allEstivalsList[val].nbr}</p>
</div>
)
}
const query = graphql`
{
postgres {
allAveragesList {
avg
}
allEstivalsList {
year
nbr
}
}
}
`;
export default DataPage;
**//Main page**
export default class App extends React.Component {
constructor(props) {
super(props);
}
state = {
value1: null,
// other values
}
render() {
return (
<div>
<p>Get state in main page: {this.state.value1}</p>
<DataPage val = {this.state.value1} />
<SelectForm clickHandler={y => { this.setState({ value1: y }); }} />
</div>
)
}
}
**//Form component**
export default class IndexPage extends React.Component {
state = {
value1: null,
}
handleClick = () => {
this.props.clickHandler(this.state.value1);
this.setState(prevState => {
return { value1: prevState.value1 };
});
};
render() {
return (
<Formlayout>
<p>Test -- Value for the selected year: {this.state.value1}</p>
<select onChange = {(e) => this.setState({ value1: e.target.value })}>
<option value="">-- Year --</option>
<option value="1">1901</option>
<option value="2">1902</option>
<option value="3">1903</option>
</select>
<button onClick={this.handleClick}>Go!</button>
</Formlayout>
)
}
}
I'd appreciate to get some directions to get the select value in the data component. As my test variable val is effectively working when used in the query, what I'd like to achieve is to apply to that variable the state from the component. And that's where I'm stuck right now.
The GraphQL query is executed at the build time, not at runtime. Have a look at the docs, it's possible to query data at build and at runtime.
https://www.gatsbyjs.org/docs/client-data-fetching/
// edit
Normally you would pre generate all (static) content pages - e.g. if you have data for 50 years, you let gatsby build those 50 pages and then you could navigate by path to the page.
If you want to pass a variable to the query, check the docs: https://www.gatsbyjs.org/docs/graphql-reference/#query-variables
query GetBlogPosts(
$limit: Int, $filter: MarkdownRemarkFilterInput, $sort: MarkdownRemarkSortInput
) {
allMarkdownRemark(
limit: $limit,
filter: $filter,
sort: $sort
) {
edges {
node {
frontmatter {
title
date(formatString: "dddd DD MMMM YYYY")
}
}
}
}
}

ButterCMS: Unknown field on RootQueryType

Hello Im trying to query data into Gatsby from ButterCMS by following the documentation in gatsby-source-buttercms(https://www.gatsbyjs.org/packages/gatsby-source-buttercms/#gatsby-source-buttercms). But got the error "unknown field allButterJob on RootQueryType". I dont know what i did wrong. Someone please take a look at this for me. Here's my gatsby-config.js:
module.exports = {
siteMetadata: {
title: 'Gatsby Default Starter',
},
plugins: [
'gatsby-plugin-react-helmet',
{
resolve: 'gatsby-source-buttercms',
options: {
authToken: '2a926fdcab34e736332a54e24649cedbaf5d0e89',
contentFields: {
keys: [ // Comma delimited list of content field keys.
'job',
'news'
],
test: 0 // Optional. Set to 1 to enable test mode for viewing draft content.
}
}
}
],
}
Here's where i made the query:
import React from 'react'
import Link from 'gatsby-link'
import HeaderlineSection from '../components/headerlineSection'
import FeatureSection from '../components/featureSection'
import TeamSection from '../components/teamSection'
import NewsSection from '../components/newsSection'
import CareerSection from '../components/careerSection'
const IndexPage = ({data}) => (
<div>
<HeaderlineSection />
<FeatureSection />
<TeamSection />
<NewsSection />
<CareerSection />
{console.log(data)}
</div>
)
export default IndexPage
export const query = graphql`
query IndexPageQuery{
allButterJob{
edges{
node{
id
title
}
}
}
}
`
RootQueryType is the top level “item” in your GraphQL schema (Gatsby v1 sets this up). So the relevant part of the error here is “unknown field allButterJob”, which is pretty self explanatory: the field/type you're trying to query doesn't exist at the top level.
It's likely that it's there under a different name. Usually I hop into Graphiql (localhost:8000/___graphql if you're running gatsby develop under the standard port), where you will see something like this in the sidebar (click on the Docs link if it isn't showing):
From here you can click on “Query” to drill down into it. (Note that this screenshot is from a Gatshy v2 app, so instead of RootQueryType it's just listed as Query.) That'll pull up a list of the fields available on Query (or in your case, RootQueryType) that looks something like this:
In this example, allSitePage is a top-level field available to query like this:
query AnythingYouLikeHere {
allSitePage {
edges {
node {
path
}
}
}
}

Resources