Optional field image and 'childImageSharp' as null | Gatsby, GraphQL & YAML - reactjs

EDIT: I ended up creating a small reproduction of my problem and posted it to Gatsby's GitHub and I ended up getting some help there.
Here's the link to that issue!
I'm sorry in advance if this issue was treated somewhere else but I couldn't find an answer to what I need.
I'm currently working with Gatsby, GraphQl and YAML files and I have multiple sections that I'm mapping over but some have images and some don't.
I defined my GraphQL by stating the image with childImageSharp
sections {
title
description
imageHere {
childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid_noBase64
}
}
}
and I saw a solution that involved adding this to my gatsby-node.js so that the paths could be properly read from my YAML files
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type allProjectPageYaml implements Node {
imageHere: [String]!
}
`;
createTypes(typeDefs);
};
Now my problem is that some sections have the imageHere field and some don't
sections:
- title: Title 1
description: Description 1
- title: Title 2
description: Description 2
imageHere: Image1
The error I get is TypeError: Cannot read property 'childImageSharp' of null
What's my workaround this?

I ended up creating a small reproduction of my problem and posted it to Gatsby's GitHub and I ended up getting some help there.
Here's the link to that issue!

Check the spelling of the filepath that ChildImageSharp is trying to reference. When I was getting this error, the img filepath needed to be corrected.

for me, it was a caching issue try delete .cache, public, dirs, or run
gatsby clean
UPDATE
if using netlify ci/cd, also need to add this into package.json
"resolutions": {
"sharp": "0.24.0"
}
https://community.netlify.com/t/error-input-file-contains-unsupported-image-format-gatsby/10891/4

You've defined imageHere as a required array of strings with this: imageHere: [String]!.
If it's actually supposed to be an optional image node, you might want to instead define it as the correct type (something like GatsbyImage, but I can't recall exactly what it is off-hand—you should be able to check in graphiql). That would look more like imageHere: GatsbyImage (no bang, no square brackets).

Related

How to optionally query references in gatsby Contentful Rich Text?

I'm trying to create a blog page that can optionally display any image assets when they exist.
First, I created a content modal in Contentful with a Rich Text named "Body", and then I created an entry with some random text in it. In Gatsby, when I try to query the data via GraphQL explorer, I can query the "raw" field inside the "body". The "references" field can not be queried unless I add at least one image asset (aka, "dummy content").
below is my graphql query
export const query = graphql`
query ($slug: String!) {
contentfulBlog(slug: { eq: $slug }, node_locale: { eq: "en-US" }) {
title
body {
raw
references {
... on ContentfulAsset {
contentful_id
__typename
gatsbyImageData(formats: AUTO, layout: FULL_WIDTH)
}
}
}
}
}
`
The problem with the above query is that if there is no image asset found in a post, it will break the query. And my goal is to be able to optionally query the references field when there are assets available. But I'm not sure how to do it.
**Updated on Aug 24th, 2021:
For anyone that is also struggling with this problem as of today:
After digging through tons of documentation and answers, I've found out that this is in fact one of the limitations of the gatsby-source-contentful plugin. In short, the plugin(v4), as it states in its documentation:
At the moment, fields that do not have at least one populated instance
will not be created in the GraphQL schema.
Not sure if this will be addressed in a future release, but currently, it is required to have at least one dummy content(embedded image, links...etc) added in your rich text body in order for the plugin to create the "references" field in the graphql schema.
Here is the official discussion thread
If the idea is to only query references if they are available you need to customize the GraphQL schema to make the field nullable (meaning it can be empty, null) because, by default, it's inferred that it isn't.
You can check for Contentful content types in: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/content-types/content-model
This would be the ideal solution. Alternatively, according to this Medium article, you can bypass it by wrapping your offending node within a Node-type object. In your case:
export const query = graphql`
query ($slug: String!) {
contentfulBlog(slug: { eq: $slug }, node_locale: { eq: "en-US" }) {
title
body {
raw
references {
... on Node {
... on ContentfulAsset {
contentful_id
__typename
gatsbyImageData(formats: AUTO, layout: FULL_WIDTH)
}
}
}
}
}
}
`
You may need to tweak it. Without knowing your data and schema structure it's impossible to guess if the query above will work alone, but get the idea. Check it in the GrahiQL playground (localhost:8000/___graphql)
Other resources:
https://github.com/gatsbyjs/gatsby/issues/20696
https://github.com/gatsbyjs/gatsby/pull/20794

Typescript & Gatsby: gatsby-plugin-ts + graphQL queries integration

I'm using gatsby-plugin-ts to generate types for my graphql page queries.
The issue I have is that all types generated return a T | undefined type for all fields, so I would need to check all query subfields before using them in any component, otherwise the compiler will throw an error.
Take gatsby-plugin-image for example. Given a query:
export const query = graphql`
query IndexPage {
banner: file(relativePath: { eq: "banner.jpg" }) {
childImageSharp {
gatsbyImageData(width: 1920)
}
}
}
`;
The result data.banner should be passed to the getImage function, though if you try to do so typescript understandably throws the following error, since undefined is not assignable to IGAtsbyImageData expected by getImage
And this is even worse when it comes to more complex queries, like the ones from the markdownremark plugin: all subfields of one query result would need to be manually checked every time. Is there a work around for this?
type of data.banner should be ImageDataLike
export interface DataBannerProps {
banner: ImageDataLike;
alt: string;
}
This appears to be caused by a bug in the gatsby-plugin-image typings. Unfortunately the typings for getImage, getSrc, etc. don't match their null-safe behaviour. This also looks like it was only partially fixed, since the troublesome | null type is down one level on { childImageSharp: { gatsbyImageData: IGatsbyImageData } | null } (at least in the GraphQL Typegen typings - YMMV).
The easiest workaround is to use a type assertion:
const result = getImage(data.banner as ImageDataLike);
This tells Typescript: "Hey, I know these types don't exactly match, but trust me, data.banner will always be an ImageDataLike".
Of course, you can avoid all this if you're happy to define your typings manually, as in #Alexey's answer.
If you want to stick with auto-generated types, I'd recommend upgrading to the official GraphQL Typegen which is built into Gatsby and kept up-to-date.

Angular Request how it works for nestjsx/crud

I've been trying for hours to make it work and I can't do it, I hope some of you have the answer to my question because it must be very simple and I am a beginner
I am using AngularJs and NestJs in Nest used the #nestjsx/crud and I went trow the request docs so, here is the problem:
This is my Angular service function
getProductsOfPiece(pieceId: number): Observable<ProductSimple[]> {
return this.http.get<ProductSimple[]>(
'api/producto/', {
params: {
fields: "id,refFabr,refCliente,descrCorta,imagen",
filter: 'pieza.id||$eq||'+ pieceId
}
}
);
}
This request gives me a 400 Bad Request, it looks like this:
/api/producto/?fields=id,refFabr,refCliente,descrCorta,imagen&filter=pieza.id%257C%257C$eq%257C%257C1
I imagine the % and the hexadecimal have something to do with the URI coding and tried to encode/decode it, but didn't work.
I also tried using the class RequestQueryBuilder of #nestjsx/crud-request from the FrontEnd usage referenced in the docs, and append it to the URL
let queryString = RequestQueryBuilder.create()
.select(["id","refFabr","refCliente","descrCorta","imagen"])
.setFilter({
field: "coleccion.id",
operator: CondOperator.EQUALS,
value: collectionId
}).query();
return this.http.get<ProductSimple[]>(
'api/producto/?'+queryString
);
but got worse result
/api/producto/?fields=id%2CrefFabr%2CrefCliente%2CdescrCorta%2Cimagen&filter%5B0%5D=pieza.id%7C%7C%24eq%7C%7C1
What I don't understand is how I do this with my Postmand and it works!
api/producto/?fields=id,refFabr,refCliente,descrCorta,imagen&filter=coleccion.id||$eq||6
How can I make it work, what is wrong with my code?
Finally got the answer, just had to set the .query(false) on the RequestQueryBuilder, this boolean parameter is for encode, seams like Angular's HttpClient class does some encoding or something to the URL so, anyway
It Works! Here is the code:
getProductsOfPiece(pieceId: number): Observable<ProductSimple[]> {
let queryString = RequestQueryBuilder.create()
.select(["id","refFabr","refCliente","descrCorta","imagen"])
.setFilter({
field: "coleccion.id",
operator: CondOperator.EQUALS,
value: collectionId
}).query(false);
return this.http.get<ProductSimple[]>(
'api/producto/?'+queryString
);
}
And you need to import
RequestQueryBuilder of #nestjsx/crud-request
npm i #nestjsx/crud-request.
Any observations are welcome...
UPDATE
To create or update
Here are de docs
Create One https://github.com/nestjsx/crud/wiki/Controllers#create-one-resource
Update One https://github.com/nestjsx/crud/wiki/Controllers#update-one-resource
Following that guide the create and update are simple
Just do POST to the API 'api/producto/' (for example) with the object as body in the request
For the Update follows similar just using the PUT method and the API with the model id 'api/producto/1' (for example)

How to create list of strings in markdown frontmatter?

I am trying to retrieve data in form of a list from markdown frontmatter using gatsbyjs and graphql. Given the List in the markdown file, the goal would be to fetch the list items into my react component for further use.
This is for my work where I want to create a website using GatsbyJS and React (that's why I can't share real code).
So far I've tried to simply fetch the data via GraphQL from frontmatter but either the field is undefined or just contains null values.
I have a frontmatter like this:
---
name: "someName"
expertise: "someExpertise"
...
technologies:
- tech1
- tech2
- tech3
---
in my js code I try to fetch data using graphql like so:
query($slug: String!) {
profile: markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "DD MMMM, YYYY")
author
expertise
name
dev_type
degree
technologies
}
}
}
I expected the output to match a form like this:
technologies = ["tech1", "tech2", "tech3"]
but I get the following error(s) when trying to compile and run the site in development environment:
Case 1.
Errors:
Int cannot represent non-integer value: "tech1"
I don't know how to fix this problem. In my understanding this should work. Already tried to create new NodeField called technologies in gatsby-node.js but this did not work, too.
I also thought about another thing according this frontmatter, in my understanding frontmatter is a YAML, or rather the desired list of technologies in the markdown file is a YAML list, isn't it?
In this case I should adjust/extend the gatsby-transformer-yaml plugin in gatsby-config.js but I have no clue how to achieve this one the right/correct way.
Case 2.
Unfortunately I cannot reproduce my query anymore but I found a way where I didn't get the type error, but then technologies only contained null values (having same frontmatter content).
technologies = [ null, null, null, ...]
Found out technologies: [ tech1, tech2, tech3 ] is the solution for this problem. Actual Problem with this was that there was inconsistent data provided in my markdown files.

Getting 'too much recursion' error when trying to serialize Qooxdoo-Object

I tried to serialize my qooxdoo-object to JSON but I always get a 'too much recursion'-errormessage (in Firebug-console) if I try the following:
qx.util.Serializer.toJson(this.getGameData())
Also .toNativeObject-function throws this error. The API-manual is very thin for this: http://www.qooxdoo.org/current/apiviewer/#qx.util.Serializer
Does anybody have a working example for me or a suggestion what could be the reason for this?
Thank you and greetings
One of your objects must have a property or similar which refers to an object which has already been serialised - there's nothing wrong with using qx.util.Serializer, but if you give it an object which has recursive references you will get a recursion error.
You can use the Qooxdoo Playground (http://www.qooxdoo.org/devel/playground/) to create an example of your problem so that others can help diagnose you problem; when you can reproduce it, use the "Shorten URL" button to create a tinyurl link.
Here's a working example of qx.util.Serializer, you can copy & paste it into the playground (SO wont let me use tinyurls :( )
qx.Class.define("abc.MyClass", {
extend: qx.core.Object,
properties: {
alpha: {
init: null,
nullable: true
}
}
});
var my = new abc.MyClass();
my.set({ alpha: 1 });
this.debug(qx.util.Serializer.toJson(my));
/* ******************************
* Show the log by clicking the "Log" button in the toolbar to see the output
*/

Resources